package com.smartleanx.module.hrm.service.employee;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.ChineseDate;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.smartleanx.framework.common.SystemConstants;
import com.smartleanx.framework.common.enums.BizTypeEnum;
import com.smartleanx.framework.common.enums.CalendarType;
import com.smartleanx.framework.common.enums.CommonStatusEnum;
import com.smartleanx.framework.common.exception.ServiceException;
import com.smartleanx.framework.common.pojo.CommonResult;
import com.smartleanx.framework.common.pojo.PageParam;
import com.smartleanx.framework.common.pojo.PageResult;
import com.smartleanx.framework.common.util.collection.CollectionUtils;
import com.smartleanx.framework.common.util.json.JsonUtils;
import com.smartleanx.framework.common.util.object.BeanUtils;
import com.smartleanx.framework.customfield.core.service.CustomFieldDataService;
import com.smartleanx.framework.customfield.core.service.bo.CustomFieldDataListReqBO;
import com.smartleanx.framework.customfield.core.service.bo.CustomFieldDataRespBO;
import com.smartleanx.framework.customfield.core.service.bo.CustomFieldDataSaveBO;
import com.smartleanx.framework.customfield.core.service.bo.inner.CustomFieldDataBaseBO;
import com.smartleanx.framework.security.core.util.SecurityFrameworkUtils;
import com.smartleanx.framework.tenant.core.aop.TenantIgnore;
import com.smartleanx.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import com.smartleanx.module.bpm.api.v2.BpmNewApi;
import com.smartleanx.module.bpm.api.v2.dto.BpmProcessTemplatesDTO;
import com.smartleanx.module.bpm.api.v2.dto.FileUploadDTO;
import com.smartleanx.module.bpm.api.v2.dto.StartProcessInstanceDTO;
import com.smartleanx.module.bpm.api.v2.dto.UserInfo;
import com.smartleanx.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import com.smartleanx.module.hrm.app.empRisk.EmployeeRiskHandleChainService;
import com.smartleanx.module.hrm.app.empRisk.EmployeeRiskHandleService;
import com.smartleanx.module.hrm.context.EmployeeContextHolder;
import com.smartleanx.module.hrm.controller.admin.employee.contract.EmployeeContractRespVO;
import com.smartleanx.module.hrm.controller.admin.employee.growth.EmployeeGrowthRecordSaveReqVO;
import com.smartleanx.module.hrm.controller.admin.employee.login.EmployeeLoginInfoRespVO;
import com.smartleanx.module.hrm.controller.admin.employee.login.EmployeeLoginInfoSaveReqVO;
import com.smartleanx.module.hrm.controller.admin.employee.regularizerecord.EmployeeRegularizeRecordRespVO;
import com.smartleanx.module.hrm.controller.admin.employee.regularizerecord.EmployeeRegularizeRecordSaveReqVO;
import com.smartleanx.module.hrm.controller.admin.employee.vo.*;
import com.smartleanx.module.hrm.controller.admin.operationlog.vo.OperationLogPageReqVO;
import com.smartleanx.module.hrm.controller.admin.operationlog.vo.OperationLogRespVO;
import com.smartleanx.module.hrm.convert.employee.contract.EmployeeConvert;
import com.smartleanx.module.hrm.dal.dataobject.dingDing.DingUser;
import com.smartleanx.module.hrm.dal.dataobject.employee.*;
import com.smartleanx.module.hrm.dal.dataobject.esign.EsignPsnInfo;
import com.smartleanx.module.hrm.dal.dataobject.payroll.PayrollDO;
import com.smartleanx.module.hrm.dal.dataobject.payroll.PayrollDetailDO;
import com.smartleanx.module.hrm.dal.dataobject.programme.bo.ProgrammeEmployeeSaveBo;
import com.smartleanx.module.hrm.dal.mysql.dingDing.DingUserMapper;
import com.smartleanx.module.hrm.dal.mysql.employee.EmployeeMapper;
import com.smartleanx.module.hrm.dal.mysql.employee.HrmMessageLogMapper;
import com.smartleanx.module.hrm.dal.mysql.esign.EsignPsnInfoMapper;
import com.smartleanx.module.hrm.eums.employee.*;
import com.smartleanx.module.hrm.eums.payroll.PayrollStateEnum;
import com.smartleanx.module.hrm.eums.risk.RiskTypeEnum;
import com.smartleanx.module.hrm.framework.excel.EasyExcelListener;
import com.smartleanx.module.hrm.framework.operate.core.annotations.OperationLog;
import com.smartleanx.module.hrm.framework.operate.core.enums.DocTypeEnum;
import com.smartleanx.module.hrm.framework.operate.core.enums.OperationTypeEnum;
import com.smartleanx.module.hrm.framework.operate.core.util.OperationLogUtils;
import com.smartleanx.module.hrm.intergration.*;
import com.smartleanx.module.hrm.service.companysystememployee.CompanySystemEmployeeService;
import com.smartleanx.module.hrm.service.employee.bo.EmployeeFileRefBo;
import com.smartleanx.module.hrm.service.employee.bo.EmployeeFileRespBo;
import com.smartleanx.module.hrm.service.employee.bo.EmployeeQueryRespBo;
import com.smartleanx.module.hrm.service.examine.util.exception.ResultException;
import com.smartleanx.module.hrm.service.operationlog.OperationLogService;
import com.smartleanx.module.hrm.service.payroll.PayrollDetailService;
import com.smartleanx.module.hrm.service.payroll.PayrollService;
import com.smartleanx.module.hrm.service.payrollapproverecord.PayrollApproveRecordDetailService;
import com.smartleanx.module.hrm.service.payrollapproverecord.PayrollApproveRecordService;
import com.smartleanx.module.hrm.service.programme.HrmProgrammeService;
import com.smartleanx.module.hrm.service.risk.RiskService;
import com.smartleanx.module.hrm.util.SendMessageUtil;
import com.smartleanx.module.infra.api.file.FileApi;
import com.smartleanx.module.infra.api.file.dto.FileRefQueryDTO;
import com.smartleanx.module.infra.api.file.dto.FileRefRespDTO;
import com.smartleanx.module.infra.api.file.dto.FileRefSaveBaseDTO;
import com.smartleanx.module.system.api.customfield.dto.CustomFieldReqDTO;
import com.smartleanx.module.system.api.customfield.dto.CustomFieldRespDTO;
import com.smartleanx.module.system.api.dept.DeptApi;
import com.smartleanx.module.system.api.dept.dto.DeptRespDTO;
import com.smartleanx.module.system.api.dept.dto.PostLevelRespDTO;
import com.smartleanx.module.system.api.dept.dto.PostRespDTO;
import com.smartleanx.module.system.api.dict.DictDataApi;
import com.smartleanx.module.system.api.dict.dto.DictDataRespDTO;
import com.smartleanx.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import com.smartleanx.module.system.api.permission.dto.RoleRespDTO;
import com.smartleanx.module.system.api.tenant.TenantApi;
import com.smartleanx.module.system.api.tenant.dto.TenantRespDTO;
import com.smartleanx.module.system.api.user.AdminUserApi;
import com.smartleanx.module.system.api.user.dto.AdminUserRespDTO;
import com.smartleanx.module.system.api.user.dto.AdminUserSaveReqDTO;
import com.smartleanx.module.system.enums.customfield.CustomFieldLabelEnum;
import com.smartleanx.module.system.enums.customfield.CustomFieldLabelGroupEnum;
import com.smartleanx.module.system.enums.customfield.CustomFieldTypeEnum;
import com.smartleanx.module.system.enums.notify.NotifyDetailTypeEnum;
import com.smartleanx.module.system.enums.notify.NotifyTemplateCodeEnum;
import com.smartleanx.module.system.enums.permission.RoleCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.smartleanx.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.smartleanx.module.hrm.enums.ErrorCodeConstants.*;

/**
 * 员工 Service 实现类
 *
 * @author tengcj
 */
@Service
@Validated
public class EmployeeServiceImpl implements EmployeeService {

    @Resource
    private EmployeeMapper employeeMapper;

    @Resource
    private FileServiceProvider fileServiceProvider;

    @Resource
    private PostServiceProvider postServiceProvider;

    @Resource
    private DeptServiceProvider deptServiceProvider;

    @Resource
    private PostLevelServiceProvider postLevelServiceProvider;

    @Resource
    private EmployeeGrowthRecordService employeeGrowthRecordService;

    @Resource
    private AdminUserServiceProvider adminUserServiceProvider;

    @Resource
    private RoleServiceProvider roleServiceProvider;

    @Resource
    private NotifyMessageServiceProvider notifyMessageServiceProvider;

    @Resource
    private EmployeeTransferRecordService employeeTransferRecordService;

    @Resource
    private OperationLogService operationLogService;

    @Resource
    private BpmServiceProvider bpmServiceProvider;

    @Resource
    private EmployeeRegularizeRecordService regularizeRecordService;

    @Resource
    private EmployeeSeparationRecordService separationRecordService;

    @Resource
    private CustomFieldDataService customFieldDataService;

    @Resource
    @Lazy
    private EmployeeContractService employeeContractService;

    @Resource
    private CustomFieldServiceProvider customFieldServiceProvider;

    @Resource
    private Validator validator;

    @Resource
    private TenantServiceProvider tenantServiceProvider;

    @Resource
    @Lazy
    private EmployeeRiskHandleChainService employeeRiskHandleChainService;

    @Resource
    @Lazy
    private EmployeeRiskHandleService employeeRiskHandleService;

    @Resource
    @Lazy
    private RiskService riskService;

    @Resource
    private PermissionServiceProvider permissionServiceProvider;

    @Autowired
    private DingUserMapper dingUserMapper;

    @Resource
    @Lazy
    private CompanySystemEmployeeService companySystemEmployeeService;

    @Resource
    @Lazy
    private EmployeeCertificateService employeeCertificateService;

    @Resource
    @Lazy
    private EmployeeEducationExperienceService employeeEducationExperienceService;

    @Resource
    @Lazy
    private EmployeeTrainingExperienceService employeeTrainingExperienceService;

    @Resource
    @Lazy
    private EmployeeWorkExperienceService employeeWorkExperienceService;

    @Resource
    @Lazy
    private PayrollService payrollService;

    @Resource
    @Lazy
    private PayrollDetailService payrollDetailService;

    @Resource
    @Lazy
    private PayrollApproveRecordService payrollApproveRecordService;

    @Resource
    @Lazy
    private PayrollApproveRecordDetailService payrollApproveRecordDetailService;

    @Resource
    private DeptApi deptApi;

    @Resource
    private AdminUserApi adminUserApi;

    @Autowired
    private HrmMessageLogMapper hrmMessageLogMapper;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private TenantApi tenantApi;

    @Resource
    private BpmNewApi bpmNewApi;

    @Resource
    private DictDataApi dictDataApi;

    @Resource
    private FileApi fileApi;

    @Autowired
    private HrmProgrammeService hrmProgrammeService;

    @Autowired
    private EsignPsnInfoMapper esignPsnInfoMapper;


    @Override
    public List<JSONObject> selectEmployeeBySelect(String employeeName) {
        List<JSONObject> resultList = new ArrayList<>();
        List<EmployeeDO> employeeDOS = employeeMapper.selectList(new LambdaQueryWrapper<EmployeeDO>() {{
            like(!ObjectUtils.isEmpty(employeeName), EmployeeDO::getName, employeeName);
        }});
        employeeDOS.forEach(employeeDO -> {
            JSONObject result = new JSONObject();
            result.put("id", employeeDO.getId());
            result.put("name", employeeDO.getName());
            resultList.add(result);
        });

        return resultList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(operateType = OperationTypeEnum.EMPLOYMENT, docType = DocTypeEnum.EMPLOYEE)
    public Long createEmployee(List<EmployeeFieldSaveReqVo> saveReqVo) {
        // EmployeeDO赋值
        Map<String, Object> map = new HashMap<>();
        List<Integer> fieldType = Stream.of(CustomFieldTypeEnum.DATE.getValue(), CustomFieldTypeEnum.DATETIME.getValue()).collect(Collectors.toList());
        saveReqVo.forEach(s -> {
            if (fieldType.contains(s.getType()) && s.getFieldValue() != null && !s.getFieldValue().equals("")) {
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = new Date(Long.parseLong(s.getFieldValue()));
                String format = formatter.format(date);
                s.setFieldValue(format);
            }
            map.put(s.getColName(), s.getFieldValue());
        });
        EmployeeDO employee = BeanUtil.toBean(map, EmployeeDO.class);
        // 数据校验
        validateEmployee(employee);

        // 正式员工
        if (employee.getEmploymentForm().equals(EmploymentFormEnum.FORMAL.getCode())) {
            employee.setState(EmployeeStatusEnum.PROBATION.getCode());
            if (Objects.isNull(employee.getProbationPeriod())) {
                throw exception(EMPLOYEE_CHOOSE_PROBATIONARY_PERIOD);
            }
            if (employee.getProbationPeriod().equals(EmployeeProbationPeriodEnum.No_probation_period.getMonth())) {
                employee.setState(EmployeeStatusEnum.REGULARIZED.getCode());
            } else {
                // 如转正日期不为空且在前日期之前
                if (Objects.nonNull(employee.getRegularizationTime())) {
                    boolean state = employee.getRegularizationTime().compareTo(LocalDateTime.now()) <= 0;
                    employee.setState(state ? EmployeeStatusEnum.REGULARIZED.getCode() : EmployeeStatusEnum.PENDING_REGULARIZATION.getCode());
                }
            }
        }
        // 非正式
        if (employee.getEmploymentForm().equals(EmploymentFormEnum.INFORMAL.getCode())) {
            employee.setState(EmployeeStatusEnum.INFORMAL_EMPLOYEE.getCode());
        }
        // 插入
        employeeMapper.insert(employee);
        // 日志相关
        OperationLogUtils.setOperationInfo(employee.getId(), Collections.singletonMap("info", "新建在职员工"));
        // 获取当前登录人
        AdminUserRespDTO loginUser = adminUserServiceProvider.getLoginUser();

        // 创建员工成长轨迹
        EmployeeGrowthRecordSaveReqVO vo = new EmployeeGrowthRecordSaveReqVO();
        vo.setEmployeeId(employee.getId());
        TenantRespDTO tenant = tenantServiceProvider.getCurrentTenant();
        vo.setContent(String.format(EmployeeGrowthEnum.ADD_NEW_EMPLOYEES.getAction(), tenant.getName()));
        vo.setAction("用户" + loginUser.getNickname() + "新建在职员工");
        vo.setEffectiveTime(employee.getCreateTime());
        employeeGrowthRecordService.createEmployeeGrowthRecord(vo);
        // 自定义字段相关

        List<CustomFieldDataBaseBO> fieldDataSaveBOS = BeanUtils.toBean(saveReqVo, CustomFieldDataBaseBO.class);
        fieldDataSaveBOS.forEach(f -> {
            f.setRecordId(employee.getId());
        });

        List<Integer> label = fieldDataSaveBOS.stream().map(CustomFieldDataBaseBO::getLabel).distinct().collect(Collectors.toList());
        List<Integer> labelGroup = fieldDataSaveBOS.stream().map(CustomFieldDataBaseBO::getLabelGroup).distinct().collect(Collectors.toList());
        CustomFieldDataSaveBO build = CustomFieldDataSaveBO.builder().datas(fieldDataSaveBOS).bizType(BizTypeEnum.EMPLOYEE.getValue())
                .labelGroups(labelGroup).labels(label).recordIds(Collections.singletonList(employee.getId())).build();
        customFieldDataService.crudData(build);

        // 风险点扫描
        employeeRiskHandleChainService.execute(Collections.singleton(employee.getId()));

        // 生成账号
        EmployeeLoginInfoSaveReqVO reqVO = new EmployeeLoginInfoSaveReqVO();
        curdLoginInfo(reqVO, employee);
        reqVO.setDeptId(employee.getDeptId());
        createLoginInfo(reqVO);
        // 返回
        return employee.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    public void createEmployeeOnTrial(EmployeeOnTrialReqVo reqVo) {
        EmployeeDO employeeDO = new EmployeeDO();
        List<DeptRespDTO> deptList = deptServiceProvider.getDeptList();
        if (CollUtil.isEmpty(deptList)) {
            throw exception(EMPLOYEE_DEPT_NOT_EXISTS);
        }
        List<PostRespDTO> postList = postServiceProvider.getPostList();
        if (CollUtil.isEmpty(postList)) {
            throw exception(EMPLOYEE_POST_NOT_EXISTS);
        }

        employeeDO.setName(reqVo.getName());
        employeeDO.setDeptId(deptList.get(0).getId());
        employeeDO.setPostId(37L);
        employeeDO.setEmployeeNo(UUID.randomUUID().toString());
        employeeDO.setEntryTime(LocalDateTime.now());
        employeeDO.setEmploymentForm(EmploymentFormEnum.FORMAL.getCode());
        employeeDO.setProbationPeriod(EmployeeProbationPeriodEnum.One_month.getMonth());
        employeeDO.setState(EmployeeStatusEnum.PROBATION.getCode());
//        Random random = new Random();
//        int randomDigit = random.nextInt(999999999) + 1;
        employeeDO.setMobile(reqVo.getMobile());
        employeeMapper.insert(employeeDO);

        // 检查登录用户名是否重复，是的话后面加数字区别
        EmployeeLoginInfoSaveReqVO login = new EmployeeLoginInfoSaveReqVO();
        login.setDeptId(employeeDO.getDeptId());
        login.setUsername(reqVo.getUsername());
        login.setEmployeeId(employeeDO.getId());
        login.setPassword(reqVo.getPassword());
        login.setRoleId(reqVo.getRoleId());
        login.setRemark("试用账号");
        createLoginInfo(login);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateEmployee(EmployeeSaveReqVO saveReqVO) {

        List<EmployeeFieldSaveReqVo> updateReqVO = saveReqVO.getUpdateReqVO();
        // 员工id
        Long recordId = updateReqVO.get(0).getRecordId();
        // 校验存在
        EmployeeDO employeeDO = employeeMapper.selectById(recordId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }

        // EmployeeDO赋值
        Map<String, Object> map = new HashMap<>();
        List<Integer> fieldType = Stream.of(CustomFieldTypeEnum.DATE.getValue(), CustomFieldTypeEnum.DATETIME.getValue()).collect(Collectors.toList());
        updateReqVO.forEach(s -> {
            if (fieldType.contains(s.getType()) && s.getFieldValue() != null && !s.getFieldValue().equals("")) {
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = new Date(Long.parseLong(s.getFieldValue()));
                String format = formatter.format(date);
                s.setFieldValue(format);
            }
            map.put(s.getColName(), s.getFieldValue());
        });
        EmployeeDO updateObj = BeanUtil.toBean(map, EmployeeDO.class);
        updateObj.setId(recordId);
        validateEmployee(updateObj);

        if (Objects.nonNull(updateObj.getEmploymentForm())) {
            if (updateObj.getEmploymentForm().equals(EmploymentFormEnum.FORMAL.getCode()) && Objects.nonNull(updateObj.getRegularizationTime())) {
                // 编辑员工信息，转正日期为今天（包含）之前，员工状态改变为已转正
                if (updateObj.getRegularizationTime().isBefore(LocalDateTime.now()) || updateObj.getRegularizationTime().compareTo(LocalDateTime.now()) == 0) {
                    if (updateObj.getState().equals(EmployeeStatusEnum.PENDING_REGULARIZATION.getCode()) || updateObj.getState().equals(EmployeeStatusEnum.PROBATION.getCode())) {
                        updateObj.setState(EmployeeStatusEnum.REGULARIZED.getCode());
                    }
                } else {
                    // 对于处于已转正状态的员工，若编辑后的转正日期在当前日期之后，员工状态转变为待转正
                    if (updateObj.getState().equals(EmployeeStatusEnum.REGULARIZED.getCode())) {
                        updateObj.setState(EmployeeStatusEnum.PENDING_REGULARIZATION.getCode());
                    }
                }
            }
        }

        // 风险点扫描
        employeeRiskHandleChainService.execute(Collections.singleton(updateObj.getId()));

        // 更新自定义字段信息
        List<CustomFieldDataBaseBO> fieldDataSaveBOS = BeanUtils.toBean(updateReqVO, CustomFieldDataBaseBO.class);
        List<Integer> label = fieldDataSaveBOS.stream().map(CustomFieldDataBaseBO::getLabel).distinct().collect(Collectors.toList());
        List<Integer> labelGroup = fieldDataSaveBOS.stream().map(CustomFieldDataBaseBO::getLabelGroup).distinct().collect(Collectors.toList());
        CustomFieldDataSaveBO build = CustomFieldDataSaveBO.builder().datas(fieldDataSaveBOS).recordIds(Collections.singletonList(updateObj.getId()))
                .bizType(BizTypeEnum.EMPLOYEE.getValue()).labelGroups(labelGroup).labels(label).build();
        customFieldDataService.crudData(build);

        // 更新员工信息
        if (label.get(0).equals(CustomFieldLabelEnum.EMPLOYEE_PERSONAL_INFO.getValue())) {
            employeeMapper.updateEmployeeInfo(updateObj);
        } else if (label.get(0).equals(CustomFieldLabelEnum.EMPLOYEE_POST_INFO.getValue())) {
            // 员工状态
            List<Integer> collect = Stream.of(EmployeeStatusEnum.TO_BE_SEPARATED.getCode(), EmployeeStatusEnum.SEPARATED.getCode()).collect(Collectors.toList());
            if (updateObj.getEmploymentForm().equals(EmploymentFormEnum.INFORMAL.getCode()) && !collect.contains(updateObj.getState())) {
                updateObj.setState(EmployeeStatusEnum.INFORMAL_EMPLOYEE.getCode());
            }
            employeeMapper.updateEmployeeDept(updateObj);
        }

        // 如有离职信息需要修改
        if (Objects.nonNull(saveReqVO.getSeparation())) {
            updateSeparation(saveReqVO.getSeparation(), updateObj);
        }
        EmployeeDO employee = employeeMapper.selectById(employeeDO.getId());
        // 如有，更新用户信息
        if (employeeDO.getUserId() != null) {
            EmployeeLoginInfoSaveReqVO reqVO = BeanUtils.toBean(employee, EmployeeLoginInfoSaveReqVO.class);
            reqVO.setId(employeeDO.getUserId());
            reqVO.setEmployeeId(recordId);
            reqVO.setPassword(null);
            updateUserInfo(reqVO, employee);
        }


    }

    public void updateSeparation(EmployeeSeparationSaveReqVo separation, EmployeeDO employeeDO) {
        EmployeeSeparationRecordDO recordDO = separationRecordService.getEmployeeSeparationRecord(separation.getId());
        if (Objects.nonNull(recordDO)) {
            recordDO.setApplySeparationTime(separation.getApplySeparationTime());
            recordDO.setSeparationTime(separation.getSeparationTime());
            recordDO.setRemarks(separation.getRemarks());
            recordDO.setSeparationReason(separation.getSeparationReason());
            recordDO.setSeparationType(separation.getSeparationType());
            separationRecordService.updateEmployeeSeparation(recordDO);
            // 处理员工状态
            if (separation.getSeparationTime().isBefore(LocalDateTime.now()) || separation.getSeparationTime().compareTo(LocalDateTime.now()) == 0) {
                employeeDO.setState(EmployeeStatusEnum.SEPARATED.getCode());
                disableUser(employeeDO);
            }
            if (separation.getSeparationTime().isAfter(LocalDateTime.now()) && employeeDO.getState().equals(EmployeeStatusEnum.SEPARATED.getCode())) {
                employeeDO.setState(EmployeeStatusEnum.TO_BE_SEPARATED.getCode());
            }
            // 更新员工信息
            employeeMapper.updateEmployeeDept(employeeDO);

        }
    }

    @Override
    @Transactional
    public void deleteEmployee(Long id) {

        EmployeeDO employeeDO = employeeMapper.selectById(id);
        if (employeeDO == null) {
            return;
        }

        // 账号id
        Long userId = employeeDO.getUserId();

        // 删除制度学习
        companySystemEmployeeService.deleteByEmployeeId(id);

        // 删除员工证书
        employeeCertificateService.deleteByEmployeeId(id);

        // 删除员工合同
        employeeContractService.deleteByEmployeeIdNew(id);

        // 删除自定义字段数据
        CustomFieldDataSaveBO build = CustomFieldDataSaveBO.builder().bizType(BizTypeEnum.EMPLOYEE.getValue())
                .labels(new ArrayList<>())
                .labelGroups(new ArrayList<>())
                .recordIds(Collections.singletonList(id)).build();
        customFieldDataService.crudData(build);

        // 删除员工教育经历
        employeeEducationExperienceService.deleteByEmployeeId(id);

        // 员工成长轨迹
        employeeGrowthRecordService.deleteByEmployeeId(id);

        // 员工培训经历
        employeeTrainingExperienceService.deleteByEmployeeId(id);

        // 工作经历
        employeeWorkExperienceService.deleteByEmployeeId(id);

        // 风险点
        riskService.deleteRisk(id, (Long) null);

        try {
            // 薪资
            PayrollDO payroll = payrollService.getPayrollByState(CollUtil.newArrayList(PayrollStateEnum.INITIAL.getValue(), PayrollStateEnum.ARCHIVING.getValue()));
            if (payroll != null) {
                List<PayrollDetailDO> detailDOS = payrollDetailService.getDetailListByPayrollIdAndEmployeeId(payroll.getId(), id);
                for (PayrollDetailDO item : detailDOS) {
                    payrollDetailService.deleteDetail(item.getId());
                }
            }
        } catch (Exception e) {
            System.err.println(e.getMessage() + "老薪资【员工删除】");
        }

        // TODO 绩效考核

        // 员工离职记录
        List<EmployeeSeparationRecordDO> separatedList = separationRecordService.getSeparatedList(id);
        for (EmployeeSeparationRecordDO item : separatedList) {
            // TODO 删除离职审批
            // 删除离职记录
            separationRecordService.deleteEmployeeSeparationRecordNew(item.getId());
        }

        // 员工转正记录
        List<EmployeeRegularizeRecordDO> regularizeList = regularizeRecordService.getRegularizeRecordList(id);
        for (EmployeeRegularizeRecordDO item : regularizeList) {
            // TODO 删除转正审批
            // 删除转正记录
            regularizeRecordService.deleteEmployeeRegularizeRecord(item.getId());
        }

        // TODO 员工调动记录
        List<EmployeeTransferRecordDO> transferList = employeeTransferRecordService.getTransferRecordList(id);
        for (EmployeeTransferRecordDO item : transferList) {
            // TODO 删除调动审批
            // 删除调动记录
            employeeTransferRecordService.deleteEmployeeTransferRecord(item.getId());
        }

        // cloud 删除账号
        adminUserServiceProvider.deleteAdminUser(userId);

        // 员工操作记录
        operationLogService.deleteByUserId(userId);


        employeeMapper.updateToDeleteById(id, System.currentTimeMillis());
    }

    public void validateEmployee(EmployeeDO employee) {
        //1.判断是新增/修改  ————》有id 为更新   更新需要判断手机号是否有修改
        if (null != employee.getId()) {
            EmployeeDO employeeDO = employeeMapper.selectById(employee.getId());
            //1.1 数据库的手机号 和 传入的手机号不相同
            if (!employeeDO.getMobile().equals(employee.getMobile())) {
                EmployeeDO employeeDO1 = employeeMapper.selectEmployeeByNameAndPhone(employee.getName(), employee.getMobile());
                if (null != employeeDO1) {
                    throw exception(EMPLOYEE_PHONE_EXISTS);
                }
            }
        } else {
            //1.2 新增员工时  需要校验手机号是否已存在
            EmployeeDO employeeDO1 = employeeMapper.selectEmployeeByNameAndPhone(employee.getName(), employee.getMobile());
            if (null != employeeDO1) {
                throw exception(EMPLOYEE_PHONE_EXISTS);
            }
        }

        // 员工编号不允许重复
        EmployeeDO employeeDO = employeeMapper.selectByEmployeeNo(employee.getEmployeeNo());
//        if (employee.getIsLeader() == 1) {
//            CommonResult<DeptRespDTO> dept = deptApi.getDept(employee.getDeptId());
//            if (!ObjectUtils.isEmpty(dept.getCheckedData().getLeaderUserId())) {
//                throw exception(is_leader_error);
//            }
//        }

        if (Objects.nonNull(employeeDO) && !employeeDO.getId().equals(employee.getId())) {
            throw exception(EMPLOYEE_NO_CANNOT_BE_REPEATED);
        }
        if (Objects.nonNull(employee.getEmploymentForm()) && employee.getEmploymentForm().equals(EmploymentFormEnum.FORMAL.getCode())) {
            if (Objects.nonNull(employee.getEmploymentType())) {
                throw exception(EMPLOYEE_STATUS_NOT_INFORMAL_TYPES);
            }
        }
        // 检查职级和岗位是否一致
        if (Objects.nonNull(employee.getPostLevelId())) {
            PostLevelRespDTO level = postLevelServiceProvider.getPostLevel(employee.getPostLevelId());
            if (Objects.isNull(level) || !level.getPostId().equals(employee.getPostId())) {
                throw exception(EMPLOYEE_POSTLEVEL_INCORRECT);
            }
        }
        // 校验电话号码
        if (employee.getMobile() != null) {
            if (!Pattern.matches("^1[3-9]\\d{9}$", employee.getMobile())) {
                throw exception(EMPLOYEE_MOBILE_INCORRECT);
            }
        }
        // 数据校验
        if (Objects.nonNull(employee.getEmploymentForm())) {
            if (!Objects.isNull(employee.getProbationPeriod()) && employee.getProbationPeriod() > 0) {
                employee.setRegularizationTime(null);
            }
            if (employee.getEmploymentForm().equals(EmploymentFormEnum.FORMAL.getCode())) {
                if (Objects.isNull(employee.getProbationPeriod())) {
                    throw exception(EMPLOYEE_CHOOSE_PROBATIONARY_PERIOD);
                }
                if (employee.getProbationPeriod() == 0 && Objects.isNull(employee.getRegularizationTime())) {
                    throw exception(EMPLOYEE_APPLYSEAPTIME_EXISTS);
                }
            }
            // 非正式
            if (employee.getEmploymentForm().equals(EmploymentFormEnum.INFORMAL.getCode())) {
                if (Objects.isNull(employee.getEmploymentType())) {
                    throw exception(EMPLOYEE_TYPE_NOT_EXISTS);
                }
            }
        }

    }

    private void validateEmployeeExists(Long id) {
        if (employeeMapper.selectById(id) == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
    }

    @Override
    public EmployeeDO getEmployeeById(Long id) {
        return employeeMapper.selectById(id);
    }

    public List<List<CustomFieldDataRespBO>> getEmployeeField(Long id, Integer label, Integer labelGroups) throws
            IllegalAccessException {
        EmployeeDO employeeDO = employeeMapper.selectById(id);
        if (Objects.isNull(employeeDO)) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        // 获取该员工自定义字段值
        CustomFieldDataListReqBO reqBO = new CustomFieldDataListReqBO();
        reqBO.setBizType(BizTypeEnum.EMPLOYEE.getValue());
        reqBO.setLabels(Collections.singletonList(label));
        reqBO.setLabelGroups(Collections.singletonList(labelGroups));
        reqBO.setRecordIds(Collections.singletonList(id));
        List<CustomFieldDataRespBO> dataList = customFieldDataService.getDataList(reqBO);

        Map<String, Object> map = BeanUtil.beanToMap(employeeDO);
        if (CollUtil.isNotEmpty(dataList)) {
            // 固定字段赋值
            for (CustomFieldDataRespBO respBO : dataList) {
                if (respBO.getIsFixed()) {
                    String colName = StringUtils.underlineToCamel(respBO.getColName());
                    if (map.get(colName) instanceof LocalDateTime && map.get(colName) != null) {
                        LocalDateTime localDateTime = (LocalDateTime) map.get(colName);
                        //  LocalDateTime 转 Instant 时间戳
//                        long milli = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                        long milli = localDateTime.toLocalDate().atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
                        map.put(colName, String.valueOf(milli));
                    }
                    respBO.setFieldValue(Objects.isNull(map.get(colName)) ? null : map.get(colName).toString());
                } else {
                    if (null != respBO.getFieldValue() && isValidTimeFormat(respBO.getFieldValue(), "yyyy-MM-dd HH:mm:ss")) {
                        long l = convertToTimestamp(respBO.getFieldValue(), "yyyy-MM-dd HH:mm:ss");
                        respBO.setFieldValue(l + "");
                    }
                }
                try {
                    if ("date_of_birth".equals(respBO.getColName())) {
                        String fieldValue = respBO.getFieldValue();
                        if (!StringUtils.isBlank(fieldValue)) {
                            LocalDate birthDate = Instant.ofEpochMilli(Long.parseLong(fieldValue)).atZone(ZoneId.systemDefault()).toLocalDate();
                            LocalDate currentDate = LocalDate.now();
                            long age = ChronoUnit.YEARS.between(birthDate, currentDate);
                            for (CustomFieldDataRespBO temp : dataList) {
                                if ("年龄".equals(temp.getName())) {
                                    temp.setFieldValue(String.valueOf(age));
                                    break;
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return CollectionUtils.convertList(
                dataList.stream()
                        .sorted(Comparator.comparingInt(CustomFieldDataRespBO::getYAxis))
                        .collect(Collectors.groupingBy(CustomFieldDataRespBO::getXAxis, TreeMap::new, Collectors.toList())).values(), Function.identity()
        );

    }

    //    判断字符串 是不是时间格式
    public static boolean isValidTimeFormat(String timeStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        try {
            LocalDateTime.parse(timeStr, formatter);
            return true;
        } catch (DateTimeParseException e) {
            return false;
        }
    }

    //  字符串时间转为时间戳
    public static long convertToTimestamp(String timeStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        LocalDateTime localDateTime = LocalDateTime.parse(timeStr, formatter);
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }


    @Override
    public EmployeeDO getEmployeeByUserId(Long userId) {
        if (userId == null) {
            return null;
        }
        return employeeMapper.selectByUserId(userId);
    }

    @Override
    public List<EmployeeDO> getEmployeeByUserIds(Set<Long> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return Collections.emptyList();
        }
        return employeeMapper.selectListByUserIds(userIds);
    }

    @Override
    public List<EmployeeDO> getEmployeeList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return employeeMapper.selectBatchIds(ids);
    }

    @Override
    public List<EmployeeDO> getEmployeeListDesc(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return employeeMapper.selectList(new LambdaQueryWrapper<EmployeeDO>() {{
            in(EmployeeDO::getId, ids);
            orderByDesc(EmployeeDO::getCreateTime);
        }});
    }

    @Override
    public List<EmployeeDO> getAllEmployee() {
        return employeeMapper.selectList();
    }

    @Override
    public List<EmployeeDO> getEmployeeListByDeptId(Collection<Long> deptIdList, Integer status) {
        if (CollUtil.isEmpty(deptIdList)) {
            return Collections.emptyList();
        }
        return employeeMapper.selectListByDeptId(deptIdList, status);
    }

    @Override
    public List<EmployeeDO> getEmployeeListByPostLevelId(Long postLevelId) {
        return employeeMapper.selectListByDeptLevelId(postLevelId);
    }

    @Override
    public List<EmployeeDO> getEmployeeListByPostId(Long postId) {
        return employeeMapper.selectListByPostId(postId);
    }

    public List<EmployeePageRespVO> curdEmployeeCustomFieldData(List<EmployeeDO> list) {

        // 部门信息
        List<Long> deptIds = CollectionUtils.convertList(list, EmployeeDO::getDeptId);
        Map<Long, DeptRespDTO> deptMap = deptServiceProvider.getDeptMap(deptIds);
        // 岗位信息
        List<Long> postIds = CollectionUtils.convertList(list, EmployeeDO::getPostId);
        Map<Long, PostRespDTO> postMap = postServiceProvider.getPostMap(postIds);
        // 员工执行中合同信息
        Map<Long, List<EmployeeContractRespVO>> contractMap = employeeContractService.getEmployeeContractMap(CollectionUtils.convertList(list, EmployeeDO::getId));
        // 获取该员工自定义字段值
        CustomFieldDataListReqBO reqBO = new CustomFieldDataListReqBO();
        reqBO.setBizType(BizTypeEnum.EMPLOYEE.getValue());
        reqBO.setLabelGroups(Collections.singletonList(CustomFieldLabelGroupEnum.EMPLOYEE_BASE_INFO.getValue()));
        reqBO.setLabels(Collections.singletonList(CustomFieldLabelEnum.EMPLOYEE_PERSONAL_INFO.getValue()));
        reqBO.setRecordIds(CollectionUtils.convertList(list, EmployeeDO::getId));
        List<CustomFieldDataRespBO> dataList = customFieldDataService.getDataList(reqBO);
        // 去掉固定字段（固定字段在员工表中已经拿到）
        dataList.removeIf(d -> !d.getIsFixed());
        // 返回值
        List<EmployeePageRespVO> respVOList = new ArrayList<>();
        for (EmployeeDO employeeDO : list) {
            EmployeePageRespVO pageRespVO = BeanUtils.toBean(employeeDO, EmployeePageRespVO.class);
            pageRespVO.setIsExpires(false);
            if (employeeDO.getState().equals(EmployeeStatusEnum.PROBATION.getCode())) {
                LocalDateTime planRegularizationTime = employeeDO.getEntryTime().plusMonths(employeeDO.getProbationPeriod()).minusDays(1);
                if (planRegularizationTime.toLocalDate().minusDays(3).compareTo(LocalDate.now()) <= 0) {
                    pageRespVO.setIsExpires(true);
                }
            }
            // 入职年限
            if (Objects.nonNull(employeeDO.getEntryTime())) {
                pageRespVO.setYears(ChronoUnit.YEARS.between(employeeDO.getEntryTime(), LocalDateTime.now()));
            }
            // 部门
            if (deptMap.size() > 0) {
                DeptRespDTO dept = deptMap.get(employeeDO.getDeptId());
                if (Objects.nonNull(dept)) {
                    pageRespVO.setDeptName(employeeDO.getDeptId() == null ? null : dept.getName());
                }
            }
            // 岗位
            if (postMap.size() > 0) {
                PostRespDTO post = postMap.get(employeeDO.getPostId());
                if (Objects.nonNull(post)) {
                    pageRespVO.setPostName(employeeDO.getPostId() == null ? null : post.getName());
                }
            }
            // 计算司龄（月）
            if (Objects.nonNull(employeeDO.getEntryTime())) {
                pageRespVO.setCompanyAge(Period.between(employeeDO.getEntryTime().toLocalDate(), LocalDate.now()).toTotalMonths());
            }
            // 现合同结束日期
            List<EmployeeContractRespVO> contractList = contractMap.get(employeeDO.getId());
            if (CollUtil.isNotEmpty(contractList)) {
                // 剔除无结束日期的
                contractList.removeIf(c -> Objects.isNull(c.getEndTime()));
                List<EmployeeContractRespVO> collect = contractList.stream().sorted(Comparator.comparing(EmployeeContractRespVO::getEndTime).reversed()).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(collect)) {
                    pageRespVO.setContractEndTime(collect.get(0).getEndTime().toLocalDate());
                }
            }
            Map<String, Object> map = BeanUtil.beanToMap(pageRespVO);
            dataList.stream().filter(i -> i.getRecordId().equals(employeeDO.getId())).forEach(d -> {
                // 非固定字段赋值
                if (!d.getIsFixed()) {
                    map.put(d.getColName(), d.getFieldValue());
                }
            });
            EmployeePageRespVO respVO = BeanUtil.toBean(map, EmployeePageRespVO.class);
            respVOList.add(respVO);
        }

        return respVOList;
    }


    // 根据员工分页数据，构建返回前端的字段（后期可优化为自定义字段样式）
    public PageResult<EmployeePageRespVO> curdEmployeePage(PageResult<EmployeeDO> pageList) {
        PageResult<EmployeePageRespVO> result = new PageResult<>();
        result.setTotal(pageList.getTotal());
        result.setList(Collections.emptyList());

        if (pageList.getTotal() > 0) {
            List<EmployeePageRespVO> respVOList = curdEmployeeCustomFieldData(pageList.getList());
            result.setList(respVOList);
        }
        return result;
    }


    public List<EmployeeExportVo> getExportEmployeeExcel(EmployeePageReqVO pageReqVO) {
        List<EmployeePageRespVO> list = getEmployeePage(pageReqVO).getList();
        return CollectionUtils.convertList(list, employee -> {
            EmployeeExportVo exportVo = BeanUtils.toBean(employee, EmployeeExportVo.class);
            if (Objects.nonNull(employee.getContractEndTime())) {
                exportVo.setContractEndTime(employee.getContractEndTime());
            }
            exportVo.setEntryTime(employee.getEntryTime().toLocalDate());
            exportVo.setCompanyAge(employee.getCompanyAge());
            exportVo.setEmploymentForm(EmploymentFormEnum.getName(employee.getEmploymentForm()));
            exportVo.setState(EmployeeStatusEnum.getName(employee.getState()));
            if (Objects.nonNull(employee.getRegularizationTime()))
                exportVo.setRegularizationTime(employee.getRegularizationTime().toLocalDate());
            return exportVo;
        });
    }

    @Override
    public PageResult<EmployeePageRespVO> getEmployeePage(EmployeePageReqVO pageReqVO) {
//        if (Objects.nonNull(pageReqVO.getState()) && pageReqVO.getState().length > 1) { // 长度大于1，默认是查在职的，手动增加待转正
//            List<Integer> collect = Arrays.stream(pageReqVO.getState()).collect(Collectors.toList());
//            collect.add(EmployeeStatusEnum.PENDING_REGULARIZATION.getCode());
//            pageReqVO.setState(collect.stream().toArray(Integer[]::new));
//        }
        PageResult<EmployeeDO> pageList = employeeMapper.selectPage(pageReqVO);
        return curdEmployeePage(pageList);
    }

    @Override
    public EmployeeRegularizeRecordRespVO getEmployeeRegularize(Long id) {
        EmployeeRegularizeRecordDO regularizeRecord = regularizeRecordService.getEmployeeRegularizeRecord(id);
        if (Objects.isNull(regularizeRecord)) {
            throw exception(EMPLOYEE_REGULARIZE_RECORD_NOT_EXISTS);
        }
        // 获取用户信息
        EmployeeBasicInfoRespVo employeeInfo = getEmployeeInfo(regularizeRecord.getEmployeeId());
        EmployeeRegularizeRecordRespVO respVO = BeanUtils.toBean(regularizeRecord, EmployeeRegularizeRecordRespVO.class);
        respVO.setEmployeeNo(employeeInfo.getEmployeeNo());
        respVO.setName(employeeInfo.getName());
        respVO.setEmploymentForm(employeeInfo.getEmploymentForm());
        respVO.setPostName(employeeInfo.getPostName());
        respVO.setDeptName(employeeInfo.getDeptName());
        respVO.setPostLevel(employeeInfo.getPostLevel());
        respVO.setEntryTime(employeeInfo.getEntryTime());
        respVO.setRegularizationTime(employeeInfo.getRegularizationTime());

        // 获取关联附件
        List<Integer> bizFileType = Stream.of(BizFileTypeEnum.PROBATION_ASSESSMENT_FORM.getCode(), BizFileTypeEnum.OTHER_IN_SERVICE_REGULARIZE.getCode()).collect(Collectors.toList());
        FileRefQueryDTO refQueryDTO = new FileRefQueryDTO();
        refQueryDTO.setBizType(BizTypeEnum.EMPLOYEE_REGULARIZED.getValue());
        refQueryDTO.setBizRecordIds(Collections.singletonList(regularizeRecord.getId()));
        refQueryDTO.setBizFileTypes(bizFileType);
        List<FileRefRespDTO> fileRefRespDTOList = fileServiceProvider.getFileRef(refQueryDTO);
        if (CollUtil.isNotEmpty(fileRefRespDTOList)) {
            respVO.setProbationFileIdList(fileRefRespDTOList.stream().filter(f -> f.getBizFileType().equals(BizFileTypeEnum.PROBATION_ASSESSMENT_FORM.getCode())).collect(Collectors.toList()));
            respVO.setOtherFileIdList(fileRefRespDTOList.stream().filter(f -> f.getBizFileType().equals(BizFileTypeEnum.OTHER_IN_SERVICE_REGULARIZE.getCode())).collect(Collectors.toList()));
        }
        return respVO;

    }

    @Override
    public List<EmployeeBasicInfoRespVo> getEmployeeInfoByIds(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        List<EmployeeDO> list = employeeMapper.selectBatchIds(ids);
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return BeanUtils.toBean(list, EmployeeBasicInfoRespVo.class);

    }

    // 获取员工基础信息
    @Override
    public EmployeeBasicInfoRespVo getEmployeeInfo(Long id) {
        if (id == null) {
            id = EmployeeContextHolder.getEmployeeId();
        }
        EmployeeDO employeeDO = employeeMapper.selectById(id);
        if (Objects.isNull(employeeDO)) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        // 头像
        AdminUserRespDTO adminUser = adminUserServiceProvider.getAdminUser(SecurityFrameworkUtils.getLoginUserId());
        EmployeeBasicInfoRespVo vo = BeanUtils.toBean(employeeDO, EmployeeBasicInfoRespVo.class);
        // 岗级
        if (Objects.nonNull(employeeDO.getPostLevelId())) {
            PostLevelRespDTO postLevel = postLevelServiceProvider.getPostLevel(employeeDO.getPostLevelId());
            vo.setPostLevel(Objects.nonNull(postLevel) ? postLevel.getName() : null);
        }
        // 部门
        if (Objects.nonNull(employeeDO.getDeptId())) {
            DeptRespDTO dept = deptServiceProvider.getDept(employeeDO.getDeptId());
            vo.setDeptName(Objects.nonNull(dept) ? dept.getName() : null);
        }
        // 岗位
        if (Objects.nonNull(employeeDO.getPostId())) {
            PostRespDTO post = postServiceProvider.getPost(employeeDO.getPostId());
            vo.setPostName(Objects.nonNull(post) ? post.getName() : null);
        }
        vo.setId(employeeDO.getId());
        vo.setName(employeeDO.getName());
        vo.setEmployeeNo(employeeDO.getEmployeeNo());
        vo.setEmploymentForm(EmploymentFormEnum.getName(employeeDO.getEmploymentForm()));
        vo.setState(employeeDO.getState());
        if (employeeDO.getEmploymentForm().equals(EmploymentFormEnum.FORMAL.getCode())) {
            vo.setPlanRegularizationTime(employeeDO.getEntryTime().plusMonths(employeeDO.getProbationPeriod()).minusDays(1));
        }
        vo.setCompanyAge(Period.between(employeeDO.getEntryTime().toLocalDate(), LocalDate.now()).toTotalMonths());
        vo.setAvatar(Objects.nonNull(adminUser.getAvatar()) ? adminUser.getAvatar() : null);
        vo.setPersonalEmail(employeeDO.getPersonalEmail());
        vo.setMobile(employeeDO.getMobile());
        vo.setSex(employeeDO.getSex());
        return vo;

    }

    // 批量获取员工基础信息
    @Override
    public List<EmployeeBasicInfoRespVo> getEmployeeInfoList(Collection<Long> ids) {
        List<EmployeeDO> employeeDOList = employeeMapper.selectBatchIds(ids);
        if (CollUtil.isEmpty(employeeDOList)) {
            return Collections.emptyList();
        }
        List<Long> deptIds = CollectionUtils.convertList(employeeDOList, EmployeeDO::getDeptId);
        List<Long> postIds = CollectionUtils.convertList(employeeDOList, EmployeeDO::getPostId);
        List<Long> postLevelIds = CollectionUtils.convertList(employeeDOList, EmployeeDO::getPostLevelId);

        Map<Long, PostRespDTO> postMap = postServiceProvider.getPostMap(postIds);
        Map<Long, DeptRespDTO> deptMap = deptServiceProvider.getDeptMap(deptIds);
        Map<Long, PostLevelRespDTO> postLevelMap = postLevelServiceProvider.getPostLevelMap(postLevelIds);
        return CollectionUtils.convertList(employeeDOList, e -> {
            EmployeeBasicInfoRespVo vo = new EmployeeBasicInfoRespVo();
            vo.setId(e.getId());
            vo.setName(e.getName());
            vo.setEmployeeNo(e.getEmployeeNo());
            vo.setEmploymentForm(EmploymentFormEnum.getName(e.getEmploymentForm()));
            vo.setDeptName(deptMap.get(e.getDeptId()).getName());
            vo.setPostName(postMap.get(e.getPostId()).getName());
            vo.setPostLevel(postLevelMap.get(e.getPostLevelId()).getName());
            vo.setState(e.getState());
            return vo;
        });

    }

    // 根据员工号，返回员工id和员工编号
    @Override
    public List<EmployeeDO> selectListByEmployeeNoS(Collection<String> employeeNos) {
        return employeeMapper.selectListByEmployeeNoS(employeeNos);
    }

    @Override
    public EmployeeDO selectByEmployeeNo(String employeeNo) {
        return employeeMapper.selectByEmployeeNo(employeeNo);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    @OperationLog(operateType = OperationTypeEnum.REJECT_A_REGULAR_EMPLOYEE, docType = DocTypeEnum.EMPLOYEE)
    public void rejectRegularize(Long id, Integer approveResult) {
        EmployeeRegularizeRecordDO regularizeRecord = regularizeRecordService.getEmployeeRegularizeRecord(id);
        if (Objects.isNull(regularizeRecord)) {
            throw exception(EMPLOYEE_REGULARIZE_RECORD_NOT_EXISTS);
        }

        EmployeeDO employeeDO = employeeMapper.selectById(regularizeRecord.getEmployeeId());
        if (Objects.isNull(employeeDO)) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }

        regularizeRecord.setApproveResult(approveResult);
        regularizeRecordService.updateRegularizeRecord(regularizeRecord);

        employeeDO.setState(EmployeeStatusEnum.PROBATION.getCode());
        employeeMapper.updateById(employeeDO);

        // 日志相关
        String action = employeeDO.getName() + "发起的转正申请" +
                (approveResult.equals(BpmProcessInstanceStatusEnum.CANCEL.getStatus()) ? "已取消" : "已被驳回");
        OperationLogUtils.setOperationInfo(regularizeRecord.getEmployeeId(), Collections.singletonMap("info", action));

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    @OperationLog(operateType = OperationTypeEnum.BECOMING_A_REGULAR_EMPLOYEE, docType = DocTypeEnum.EMPLOYEE)
    public void approvedRegularize(Long id, Integer approveResult) {
        EmployeeRegularizeRecordDO regularizeRecord = regularizeRecordService.getEmployeeRegularizeRecord(id);
        if (Objects.isNull(regularizeRecord)) {
            throw exception(EMPLOYEE_REGULARIZE_RECORD_NOT_EXISTS);
        }
        EmployeeDO employeeDO = employeeMapper.selectById(regularizeRecord.getEmployeeId());
        // 如果生效日期是当前之前（包含今天），则直接转正
        if (regularizeRecord.getRegularizationTime().isBefore(LocalDateTime.now()) || regularizeRecord.getRegularizationTime().compareTo(LocalDateTime.now()) == 0) {
            employeeDO.setState(EmployeeStatusEnum.REGULARIZED.getCode());
        }
        employeeMapper.updateById(employeeDO);
        if (Objects.isNull(employeeDO)) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        regularizeRecord.setApproveResult(approveResult);
        regularizeRecordService.updateRegularizeRecord(regularizeRecord);

        // 日志相关
        String action = employeeDO.getName() + "发起的转正申请已被通过";
        OperationLogUtils.setOperationInfo(regularizeRecord.getEmployeeId(), Collections.singletonMap("info", action));
        // 风险扫描
        employeeRiskHandleService.execute(Collections.singleton(employeeDO.getId()), RiskTypeEnum.PROBATIONARY_APPRAISAL_FORM.getCode());

    }

    @Override
    public EmployeeBasicInfoRespVo validateRegularize() {
        Long employeeId = EmployeeContextHolder.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
//        if (!employeeDO.getState().equals(EmployeeStatusEnum.PROBATION.getCode())) {
//            throw exception(EMPLOYEE_REGULARIZE_RECORD_EXISTING);
//        }
        return getEmployeeInfo(employeeId);
    }

    @Override
    public BpmProcessTemplatesDTO validateRegularizeNew(String type, Integer tgType) {
        Long employeeId = EmployeeContextHolder.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (!employeeDO.getState().equals(EmployeeStatusEnum.PROBATION.getCode())) {
            throw exception(EMPLOYEE_REGULARIZE_RECORD_EXISTING);
        }
        CommonResult<BpmProcessTemplatesDTO> result = bpmNewApi.processDetail(type, tgType);
        return result.getData();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    @OperationLog(operateType = OperationTypeEnum.SUBMIT_REGULAR_EMPLOYEE, docType = DocTypeEnum.EMPLOYEE)
    public void employeeRegularize(EmployeeRegularizeRecordSaveReqVO regularizeReqVO) {
        /*
        Long employeeId = regularizeReqVO.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        if (!EmployeeStatusEnum.PROBATION.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_REGULARIZE);
        }

        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        // 添加附件关联关系
        createFileRefList(regularizeReqVO.getProbationFileIdList(), BizFileTypeEnum.PROBATION_ASSESSMENT_FORM.getCode(), fileRefList);
        createFileRefList(regularizeReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_REGULARIZE.getCode(), fileRefList);

        AdminUserRespDTO loginUser = adminUserServiceProvider.getLoginUser();

        String action = loginUser.getNickname() + "发起了转正申请";
        // 日志相关
        OperationLogUtils.setOperationInfo(regularizeReqVO.getEmployeeId(), Collections.singletonMap("info", action));

        // 创建转正记录
        EmployeeRegularizeRecordDO recordDO = BeanUtils.toBean(regularizeReqVO, EmployeeRegularizeRecordDO.class);
        recordDO.setCreateType(EmployeeRecordTypeEnum.EMPLOYEE.getType());
        regularizeRecordService.createRegularizeRecord(recordDO);

        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = bpmServiceProvider.createProcessInstance(
                new BpmProcessInstanceCreateReqDTO()
                        .setProcessDefinitionKey(ProcessDefinitionEnum.REGULARIZE.getKey())
                        .setVariables(processInstanceVariables)
                        .setBusinessKey(recordDO.getId().toString())
        );

        EmployeeRegularizeRecordDO updateObj = new EmployeeRegularizeRecordDO();
        updateObj.setId(recordDO.getId());
        updateObj.setApproveResult(BpmProcessInstanceStatusEnum.RUNNING.getStatus());
        updateObj.setApproveProcessInstanceId(processInstanceId);
        regularizeRecordService.updateRegularizeRecord(updateObj);

        // 处理员工状态
        employeeDO.setRegularizationTime(regularizeReqVO.getRegularizationTime());
        // 转正提交后，待转正状态
        employeeDO.setState(EmployeeStatusEnum.PENDING_REGULARIZATION.getCode());
        employeeMapper.updateById(employeeDO);

        // 插入附件关联信息，员工端转正相关的附件，关联转正申请记录id
        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_REGULARIZED.getValue(), updateObj.getId());
*/
    }

    @Override
    public void employeeRegularizeNew(StartProcessInstanceDTO param) {

        Long employeeId = param.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        if (!EmployeeStatusEnum.PROBATION.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_REGULARIZE);
        }

        com.alibaba.fastjson2.JSONObject formData = param.getFormData();

        String regularizationTimeValue = formData.getString("zz_regularization_time");
        String jobUnderstand = formData.getString("zz_job_understand");
        String workSummary = formData.getString("zz_work_summary");
        String directionGoals = formData.getString("zz_direction_goals");
        String remarks = formData.getString("zz_remarks");

        List<FileUploadDTO> probationFileValue = formData.getList("zz_probation_file", FileUploadDTO.class);
        List<Long> probationFileIdList = probationFileValue != null ? probationFileValue.stream().map(FileUploadDTO::getId).collect(Collectors.toList()) : null;

        List<FileUploadDTO> otherFileValue = formData.getList("zz_other_file", FileUploadDTO.class);
        List<Long> otherFileIdList = otherFileValue != null ? otherFileValue.stream().map(FileUploadDTO::getId).collect(Collectors.toList()) : null;

        EmployeeRegularizeRecordSaveReqVO req = new EmployeeRegularizeRecordSaveReqVO();
        req.setId(param.getEmployeeId());
        req.setEmployeeId(param.getEmployeeId());
        req.setEntryTime(employeeDO.getEntryTime());
        req.setPlanRegularizationTime(employeeDO.getPlanSeparationTime());
        req.setRegularizationTime(LocalDateTime.parse(regularizationTimeValue + " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        req.setJobUnderstand(jobUnderstand);
        req.setWorkSummary(workSummary);
        req.setDirectionGoals(directionGoals);
        req.setRemarks(remarks);
        req.setProbationFileIdList(probationFileIdList);
        req.setOtherFileIdList(otherFileIdList);

        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        // 添加附件关联关系
        createFileRefList(req.getProbationFileIdList(), BizFileTypeEnum.PROBATION_ASSESSMENT_FORM.getCode(), fileRefList);
        createFileRefList(req.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_REGULARIZE.getCode(), fileRefList);

        AdminUserRespDTO loginUser = adminUserServiceProvider.getLoginUser();
        String action = loginUser.getNickname() + "发起了转正申请";
        // 日志相关
        OperationLogUtils.setOperationInfo(param.getEmployeeId(), Collections.singletonMap("info", action));

        // 创建转正记录
        EmployeeRegularizeRecordDO recordDO = BeanUtils.toBean(req, EmployeeRegularizeRecordDO.class);
        recordDO.setCreateType(EmployeeRecordTypeEnum.EMPLOYEE.getType());
        regularizeRecordService.createRegularizeRecord(recordDO);

        // 发起审批
        param.setBusinessId(recordDO.getId().toString());
        CommonResult<Object> result = bpmNewApi.processStart(param);
        String processInstanceId = result.getData().toString();

        EmployeeRegularizeRecordDO updateObj = new EmployeeRegularizeRecordDO();
        updateObj.setId(recordDO.getId());
        updateObj.setApproveResult(BpmProcessInstanceStatusEnum.RUNNING.getStatus());
        updateObj.setApproveProcessInstanceId(processInstanceId);
        regularizeRecordService.updateRegularizeRecord(updateObj);

        // 处理员工状态
        employeeDO.setRegularizationTime(req.getRegularizationTime());
        // 转正提交后，待转正状态
        employeeDO.setState(EmployeeStatusEnum.PENDING_REGULARIZATION.getCode());
        employeeMapper.updateById(employeeDO);

        // 插入附件关联信息，员工端转正相关的附件，关联转正申请记录id
        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_REGULARIZED.getValue(), updateObj.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    @OperationLog(operateType = OperationTypeEnum.BECOMING_A_REGULAR_EMPLOYEE, docType = DocTypeEnum.EMPLOYEE)
    public void regularize(EmployeeRegularizeRecordSaveReqVO regularizeReqVO) {
        Long employeeId = regularizeReqVO.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        if (!EmployeeStatusEnum.PROBATION.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_REGULARIZE);
        }

        // 创建转正记录
        EmployeeRegularizeRecordDO recordDO = BeanUtils.toBean(regularizeReqVO, EmployeeRegularizeRecordDO.class);
        recordDO.setApproveResult(BpmProcessInstanceStatusEnum.APPROVE.getStatus());
        recordDO.setCreateType(EmployeeRecordTypeEnum.Management.getType());
        regularizeRecordService.createRegularizeRecord(recordDO);

        employeeDO.setId(employeeId);
        employeeDO.setRegularizationTime(regularizeReqVO.getRegularizationTime());
        // 转正提交后，待转正状态
        employeeDO.setState(EmployeeStatusEnum.PENDING_REGULARIZATION.getCode());
        // 如果生效日期是当前之前（包含今天），则直接转正
        if (regularizeReqVO.getRegularizationTime().isBefore(LocalDateTime.now()) || regularizeReqVO.getRegularizationTime().compareTo(LocalDateTime.now()) == 0) {
            employeeDO.setState(EmployeeStatusEnum.REGULARIZED.getCode());
        }
        employeeMapper.updateById(employeeDO);
        // 创建员工成长轨迹
        EmployeeGrowthRecordSaveReqVO vo = new EmployeeGrowthRecordSaveReqVO();
        vo.setEmployeeId(regularizeReqVO.getEmployeeId());
        vo.setContent(EmployeeGrowthEnum.EMPLOYEE_REGULARIZATION.getAction());
        LocalDateTime regularizationTime = employeeDO.getRegularizationTime();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        vo.setAction("用户" + employeeDO.getName() + "将于" + formatter.format(regularizationTime) + " 转为正式员工");
        vo.setEffectiveTime(regularizeReqVO.getRegularizationTime());
        employeeGrowthRecordService.createEmployeeGrowthRecord(vo);
        // 日志相关
        OperationLogUtils.setOperationInfo(regularizeReqVO.getEmployeeId(), Collections.singletonMap("info", "转为正式员工"));
        // 添加附件关联关系
        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        createFileRefList(regularizeReqVO.getProbationFileIdList(), BizFileTypeEnum.PROBATION_ASSESSMENT_FORM.getCode(), fileRefList);
        createFileRefList(regularizeReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_REGULARIZE.getCode(), fileRefList);
        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_REGULARIZED.getValue(), recordDO.getId());
        // 风险扫描
        employeeRiskHandleService.execute(Collections.singleton(employeeDO.getId()), RiskTypeEnum.PROBATIONARY_APPRAISAL_FORM.getCode());
    }

    public static void main(String[] args) {

        for (int i = 0; i < 20; i++) {
            Random random = new Random();
            Long randomDigit = random.nextLong() % (long) Math.pow(10, 11);
//            if(randomDigit.longValue())
            System.err.println(String.valueOf(randomDigit).replace("-", "1"));
        }

    }

    @Override
    public EmployeeChangePostRespVO getEmployeeChangePost(Long id) {
        // 提交的记录
        EmployeeTransferRecordDO transferRecord = employeeTransferRecordService.getEmployeeTransferRecord(id);
        if (Objects.isNull(transferRecord)) {
            throw exception(EMPLOYEE_TRANSFER_RECORD_NOT_EXISTS);
        }
        EmployeeDO employeeDO = employeeMapper.selectById(transferRecord.getEmployeeId());
        if (Objects.isNull(employeeDO)) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        EmployeeChangePostRespVO changePostRespVO = BeanUtils.toBean(transferRecord, EmployeeChangePostRespVO.class);
        // 获取岗位信息
        List<Long> postIds = Stream.of(transferRecord.getNewPostId(), transferRecord.getOldPostId()).collect(Collectors.toList());
        Map<Long, PostRespDTO> postMap = postServiceProvider.getPostMap(postIds);
        if (Objects.nonNull(postMap)) {
            changePostRespVO.setNewPostId(Objects.nonNull(postMap.get(transferRecord.getNewPostId())) ? postMap.get(transferRecord.getNewPostId()).getId() : null);
            changePostRespVO.setOldPostId(Objects.nonNull(postMap.get(transferRecord.getOldPostId())) ? postMap.get(transferRecord.getOldPostId()).getId() : null);
        }

        // 获取部门信息
        List<Long> deptIds = Stream.of(transferRecord.getNewDeptId(), transferRecord.getOldDeptId()).collect(Collectors.toList());
        Map<Long, DeptRespDTO> deptMap = deptServiceProvider.getDeptMap(deptIds);
        if (Objects.nonNull(deptMap)) {
            changePostRespVO.setNewDeptId(Objects.nonNull(deptMap.get(transferRecord.getNewDeptId())) ? deptMap.get(transferRecord.getNewDeptId()).getId() : null);
            changePostRespVO.setOldDeptId(Objects.nonNull(deptMap.get(transferRecord.getOldDeptId())) ? deptMap.get(transferRecord.getOldDeptId()).getId() : null);
        }

        // 获取岗级信息
        List<Long> postLevelIds = Stream.of(transferRecord.getNewPostLevel(), transferRecord.getOldPostLevel()).collect(Collectors.toList());
        Map<Long, PostLevelRespDTO> postLevelMap = postLevelServiceProvider.getPostLevelMap(postLevelIds);

        if (Objects.nonNull(postLevelMap)) {
            changePostRespVO.setNewPostLevel(Objects.nonNull(postLevelMap.get(transferRecord.getNewPostLevel())) ? postLevelMap.get(transferRecord.getNewPostLevel()).getId() : null);
            changePostRespVO.setOldPostLevel(Objects.nonNull(postLevelMap.get(transferRecord.getOldPostLevel())) ? postLevelMap.get(transferRecord.getOldPostLevel()).getId() : null);
        }

        changePostRespVO.setChangeType(transferRecord.getChangeType());
        changePostRespVO.setChangeReason(transferRecord.getChangeReason());
        changePostRespVO.setEmployeeId(employeeDO.getId());
        changePostRespVO.setEmployeeNo(employeeDO.getEmployeeNo());
        changePostRespVO.setName(employeeDO.getName());

        // 附件相关
        FileRefQueryDTO refQueryDTO = new FileRefQueryDTO();
        refQueryDTO.setBizType(BizTypeEnum.EMPLOYEE_CHANGE_POST.getValue());
        refQueryDTO.setBizRecordIds(Arrays.asList(transferRecord.getId()));
        List<FileRefRespDTO> fileRefRespDTOList = fileServiceProvider.getFileRef(refQueryDTO);
        if (CollUtil.isNotEmpty(fileRefRespDTOList)) {
            // 调岗
            if (ChangeTypeEnum.CHANGE_POST.getCode().equals(transferRecord.getChangeType())) {
                changePostRespVO.setOtherFileIdList(fileRefRespDTOList.stream().filter(f -> f.getBizFileType().equals(BizFileTypeEnum.OTHER_IN_SERVICE_CHANGEPOST.getCode())).collect(Collectors.toList()));
                changePostRespVO.setApplyFileIdList(fileRefRespDTOList.stream().filter(f -> f.getBizFileType().equals(BizFileTypeEnum.TRANSFER_APPLICATION_FORM.getCode())).collect(Collectors.toList()));
            }
            // 晋升
            if (ChangeTypeEnum.PROMOTED.getCode().equals(transferRecord.getChangeType())) {
                changePostRespVO.setOtherFileIdList(fileRefRespDTOList.stream().filter(f -> f.getBizFileType().equals(BizFileTypeEnum.OTHER_IN_SERVICE_PROMOTED.getCode())).collect(Collectors.toList()));
                changePostRespVO.setApplyFileIdList(fileRefRespDTOList.stream().filter(f -> f.getBizFileType().equals(BizFileTypeEnum.PROMOTION_APPLICATION_FORM.getCode())).collect(Collectors.toList()));
            }
            // 降级
            if (ChangeTypeEnum.DEGRADE.getCode().equals(transferRecord.getChangeType())) {
                changePostRespVO.setOtherFileIdList(fileRefRespDTOList.stream().filter(f -> f.getBizFileType().equals(BizFileTypeEnum.OTHER_IN_SERVICE_DEGRADE.getCode())).collect(Collectors.toList()));
                changePostRespVO.setApplyFileIdList(fileRefRespDTOList.stream().filter(f -> f.getBizFileType().equals(BizFileTypeEnum.DOWNGRADE_APPLICATION_FORM.getCode())).collect(Collectors.toList()));
            }
        }
        return changePostRespVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.EMPLOYEE_APPROVED_TRANSFER)
    @Override
    public void approvedChangePost(Long id, Integer approveResult) {
        EmployeeTransferRecordDO transferRecord = employeeTransferRecordService.getEmployeeTransferRecord(id);
        if (Objects.isNull(transferRecord)) {
            throw exception(EMPLOYEE_TRANSFER_RECORD_NOT_EXISTS);
        }
        EmployeeDO employeeDO = employeeMapper.selectById(transferRecord.getEmployeeId());
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }

        System.err.println(approveResult + "审批通过状态");
        transferRecord.setApproveResult(approveResult);
        employeeTransferRecordService.updateEmployeeTransferRecord(transferRecord);

        // 如果生效时间在当前时间之前（包含），则调动直接生效
        if (transferRecord.getEffectTime().isBefore(LocalDateTime.now()) || transferRecord.getEffectTime().compareTo(LocalDateTime.now()) == 0) {
            employeeDO.setPostId(Objects.nonNull(transferRecord.getNewPostId()) ? transferRecord.getNewPostId() : employeeDO.getPostId());
            employeeDO.setDeptId(Objects.nonNull(transferRecord.getNewDeptId()) ? transferRecord.getNewDeptId() : employeeDO.getDeptId());
            employeeDO.setPostLevelId(Objects.nonNull(transferRecord.getNewPostLevel()) ? transferRecord.getNewPostLevel() : employeeDO.getPostLevelId());
        }
        employeeMapper.updateById(employeeDO);
        // 日志相关
        String action = employeeDO.getName() + "发起的调动申请已被通过";
        OperationLogUtils.setOperationInfo(transferRecord.getEmployeeId(), Collections.singletonMap("info", action));
        // 风险扫描
        // 调岗
        if (ChangeTypeEnum.CHANGE_POST.getCode().equals(transferRecord.getChangeType())) {
            employeeRiskHandleService.execute(Collections.singleton(employeeDO.getId()), RiskTypeEnum.TRANSFER_APPLICATION_FORM.getCode());
        }
        // 降级
        if (ChangeTypeEnum.DEGRADE.getCode().equals(transferRecord.getChangeType())) {
            employeeRiskHandleService.execute(Collections.singleton(employeeDO.getId()), RiskTypeEnum.DEMOTION_NOTICE_FORM.getCode());
        }
        // 风险
        changePostForRegulationRisk(employeeDO);
        // 同步风险部门
        riskService.changeEmpRiskDept(employeeDO.getId(), employeeDO.getDeptId());
        // 如有，更新用户信息
        if (employeeDO.getUserId() != null) {
            EmployeeLoginInfoSaveReqVO reqVO = BeanUtils.toBean(employeeDO, EmployeeLoginInfoSaveReqVO.class);
            reqVO.setId(employeeDO.getUserId());
            reqVO.setEmployeeId(employeeDO.getId());
            reqVO.setPassword(null);
            updateUserInfo(reqVO, employeeDO);
        }
    }

    /**
     * 员工调动-制度风险相关处理
     *
     * @param employeeDO
     */
    private void changePostForRegulationRisk(EmployeeDO employeeDO) {
        // 清空之前制度相关的风险重新扫描
        riskService.deleteRisk(Collections.singleton(employeeDO.getId()), RiskTypeEnum.REGULATION_NOT_INFORM.getCode());
        // 人事异动时，检查规章制度制定及实施风险
        employeeRiskHandleService.execute(Collections.singleton(employeeDO.getId()), RiskTypeEnum.REGULATION_NOT_INFORM.getCode());
    }

    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.EMPLOYEE_REJECT_TRANSFER)
    @Override
    public void rejectChangePost(Long id, Integer approveResult) {
        EmployeeTransferRecordDO transferRecord = employeeTransferRecordService.getEmployeeTransferRecord(id);
        if (Objects.isNull(transferRecord)) {
            throw exception(EMPLOYEE_TRANSFER_RECORD_NOT_EXISTS);
        }
        EmployeeDO employeeDO = employeeMapper.selectById(transferRecord.getEmployeeId());
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }

        transferRecord.setApproveResult(approveResult);
        employeeTransferRecordService.updateEmployeeTransferRecord(transferRecord);

        // 日志相关
        String action = employeeDO.getName() + "发起的调动申请" +
                (approveResult.equals(BpmProcessInstanceStatusEnum.CANCEL.getStatus()) ? "已取消" : "已被驳回");
        OperationLogUtils.setOperationInfo(transferRecord.getEmployeeId(), Collections.singletonMap("info", action));

    }

    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.EMPLOYEE_TRANSFER)
    public void employeeChangePost(EmployeeChangePostSaveReqVO changePostReqVO) {
        Long employeeId = changePostReqVO.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        if (EmployeeStatusEnum.TO_BE_SEPARATED.getCode().equals(employeeDO.getState()) ||
                EmployeeStatusEnum.SEPARATED.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_CHANGE_POST);
        }

        AdminUserRespDTO loginUser = adminUserServiceProvider.getLoginUser();

        // 日志相关
        StringBuilder action = new StringBuilder(loginUser.getNickname() + "发起了");
        StringBuilder actionType = new StringBuilder();
        // 审批流类型
        StringBuilder processDefinitionKey = new StringBuilder();

        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        // 调岗
        if (ChangeTypeEnum.CHANGE_POST.getCode().equals(changePostReqVO.getChangeType())) {
            createFileRefList(changePostReqVO.getApplyFileIdList(), BizFileTypeEnum.TRANSFER_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(changePostReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_CHANGEPOST.getCode(), fileRefList);
            actionType.append("【调岗】");
            processDefinitionKey.append(ProcessDefinitionEnum.CHANGE_POST.getKey());

        }
        // 晋升
        if (ChangeTypeEnum.PROMOTED.getCode().equals(changePostReqVO.getChangeType())) {
            createFileRefList(changePostReqVO.getApplyFileIdList(), BizFileTypeEnum.PROMOTION_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(changePostReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_PROMOTED.getCode(), fileRefList);
            actionType.append("【晋升】");
            processDefinitionKey.append(ProcessDefinitionEnum.PROMOTED.getKey());
        }
        // 降级
        if (ChangeTypeEnum.DEGRADE.getCode().equals(changePostReqVO.getChangeType())) {
            createFileRefList(changePostReqVO.getApplyFileIdList(), BizFileTypeEnum.DOWNGRADE_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(changePostReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_DEGRADE.getCode(), fileRefList);
            actionType.append("【降级】");
            processDefinitionKey.append(ProcessDefinitionEnum.DEGRADE.getKey());
        }
        String actionEnd = "申请";
        action.append(actionType).append(actionEnd);

        // 插入日志相关话术
        OperationLogUtils.setOperationInfo(employeeId, Collections.singletonMap("info", action));

        // 插入记录
        EmployeeTransferRecordDO recordDO = BeanUtils.toBean(changePostReqVO, EmployeeTransferRecordDO.class);
        recordDO.setCreateType(EmployeeRecordTypeEnum.EMPLOYEE.getType());
        employeeTransferRecordService.createEmployeeChangeRecord(recordDO);


        // 审核相关
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();

        String processInstanceId = bpmServiceProvider.createProcessInstance(
                new BpmProcessInstanceCreateReqDTO()
                        .setProcessDefinitionKey(processDefinitionKey.toString())
                        .setVariables(processInstanceVariables)
                        .setBusinessKey(recordDO.getId().toString())
        );

        recordDO.setApproveResult(BpmProcessInstanceStatusEnum.RUNNING.getStatus());
        recordDO.setApproveProcessInstanceId(processInstanceId);
        employeeTransferRecordService.updateEmployeeTransferRecord(recordDO);

        // 相关附件 员工端提交记录时，附件关联调动记录id
        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_CHANGE_POST.getValue(), recordDO.getId());

    }

    @Override
    public void employeeChangePostNew(StartProcessInstanceDTO param) {
        Long employeeId = param.getEmployeeId();
        Integer ddChangePostType = param.getDd_change_post_type();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        if (EmployeeStatusEnum.TO_BE_SEPARATED.getCode().equals(employeeDO.getState()) ||
                EmployeeStatusEnum.SEPARATED.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_CHANGE_POST);
        }

        AdminUserRespDTO loginUser = adminUserServiceProvider.getLoginUser();

        com.alibaba.fastjson2.JSONObject formData = param.getFormData();
//        String changePostTypeKey = formData.getString("dd_change_post_type");
        CommonResult<DictDataRespDTO> dictDataRespDTOCommonResult = dictDataApi.getDictData("hrm_change_post_type", ddChangePostType.toString());
//        CommonResult<DictDataRespDTO> dictDataRespDTOCommonResult = dictDataApi.parseDictData("hrm_change_post_type", changePostTypeKey);
        String changePostTypeValue = dictDataRespDTOCommonResult.getData().getValue();

        String changePostReasonKey = formData.getString("dd_change_post_reason");
        CommonResult<DictDataRespDTO> dictDataRespDTOCommonResult1 = dictDataApi.parseDictData("hrm_change_post_reason", changePostReasonKey);
        String changePostReasonValue = dictDataRespDTOCommonResult1.getData().getValue();

        String newDeptId = formData.getList("dd_new_dept_id", UserInfo.class).get(0).getId();
        String newPostId = formData.getString("dd_new_post_id");
        String newPostLevel = formData.getString("dd_new_post_level");
        String effectTime = formData.getString("dd_effect_time");
        String remarks = formData.getString("dd_remarks");

        List<FileUploadDTO> applyFileValue = formData.getList("dd_apply_file", FileUploadDTO.class);
        List<Long> applyFileIdList = applyFileValue != null ? applyFileValue.stream().map(FileUploadDTO::getId).collect(Collectors.toList()) : null;

        List<FileUploadDTO> otherFileValue = formData.getList("lz_other_file", FileUploadDTO.class);
        List<Long> otherFileIdList = otherFileValue != null ? otherFileValue.stream().map(FileUploadDTO::getId).collect(Collectors.toList()) : null;

        EmployeeChangePostSaveReqVO req = new EmployeeChangePostSaveReqVO();
        req.setEmployeeId(param.getEmployeeId());
        req.setChangeType(Integer.valueOf(changePostTypeValue));
        req.setChangeReason(Integer.valueOf(changePostReasonValue));
        // 变更前后部门
        req.setOldDeptId(employeeDO.getDeptId());
        req.setNewDeptId(Long.valueOf(newDeptId));
        req.setOldPostId(employeeDO.getPostId());
        req.setNewPostId(Long.valueOf(newPostId));
        req.setOldPostLevel(employeeDO.getPostLevelId());
        req.setNewPostLevel(Long.valueOf(newPostLevel));
        req.setEffectTime(LocalDateTime.parse(effectTime + "-01 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        req.setRemarks(remarks);
        req.setApplyFileIdList(applyFileIdList);
        req.setOtherFileIdList(otherFileIdList);
        // 日志相关
        StringBuilder action = new StringBuilder(loginUser.getNickname() + "发起了");
        action.append("【").append(dictDataRespDTOCommonResult.getData().getLabel()).append("】申请");
        // 插入日志相关话术
        OperationLogUtils.setOperationInfo(employeeId, Collections.singletonMap("info", action));

        // 插入记录
        EmployeeTransferRecordDO recordDO = BeanUtils.toBean(req, EmployeeTransferRecordDO.class);
        recordDO.setCreateType(EmployeeRecordTypeEnum.EMPLOYEE.getType());
        recordDO.setApproveResult(BpmProcessInstanceStatusEnum.RUNNING.getStatus());
        employeeTransferRecordService.createEmployeeChangeRecord(recordDO);

        // 发起审批
        param.setBusinessId(recordDO.getId().toString());
        CommonResult<Object> result = bpmNewApi.processStart(param);
        String processInstanceId = result.getData().toString();
        recordDO.setApproveProcessInstanceId(processInstanceId);
        employeeTransferRecordService.updateEmployeeTransferRecord(recordDO);

        // 相关附件 员工端提交记录时，附件关联调动记录id
        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        if ("调岗".equals(dictDataRespDTOCommonResult.getData().getLabel())) {
            createFileRefList(req.getApplyFileIdList(), BizFileTypeEnum.TRANSFER_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(req.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_CHANGEPOST.getCode(), fileRefList);
        }
        if ("晋升".equals(dictDataRespDTOCommonResult.getData().getLabel())) {
            createFileRefList(req.getApplyFileIdList(), BizFileTypeEnum.PROMOTION_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(req.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_PROMOTED.getCode(), fileRefList);
        }
        if ("降级".equals(dictDataRespDTOCommonResult.getData().getLabel())) {
            createFileRefList(req.getApplyFileIdList(), BizFileTypeEnum.DOWNGRADE_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(req.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_DEGRADE.getCode(), fileRefList);
        }
        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_CHANGE_POST.getValue(), recordDO.getId());
    }


    @Override
    public EmployeeBasicInfoRespVo validateChangePost() {
        Long employeeId = EmployeeContextHolder.getEmployeeId();
        List<EmployeeTransferRecordDO> recordList = employeeTransferRecordService.getTransferRecordList(employeeId);
        List<EmployeeTransferRecordDO> collect = recordList.stream().filter(r -> r.getApproveResult().equals(BpmProcessInstanceStatusEnum.RUNNING.getStatus())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            throw exception(EMPLOYEE_TRANSFER_RECORD_EXISTING);
        }
        return getEmployeeInfo(employeeId);
    }


    @Override
    public BpmProcessTemplatesDTO validateChangePostNew(String type, Integer tgType) {
        Long employeeId = EmployeeContextHolder.getEmployeeId();
        List<EmployeeTransferRecordDO> recordList = employeeTransferRecordService.getTransferRecordList(employeeId);
        List<EmployeeTransferRecordDO> collect = recordList.stream().filter(r -> r.getApproveResult().equals(BpmProcessInstanceStatusEnum.RUNNING.getStatus())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            throw exception(EMPLOYEE_TRANSFER_RECORD_EXISTING);
        }
        CommonResult<BpmProcessTemplatesDTO> result = bpmNewApi.processDetail(type, tgType);
        return result.getData();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.EMPLOYEE_TRANSFER)
    public void changePost(EmployeeChangePostSaveReqVO changePostReqVO) {
        Long employeeId = changePostReqVO.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        // 待离职和已离职状态下不允许进行调动操作
        if (EmployeeStatusEnum.TO_BE_SEPARATED.getCode().equals(employeeDO.getState()) ||
                EmployeeStatusEnum.SEPARATED.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_CHANGE_POST);
        }

        // 检查职级和岗位是否一致
        if (Objects.nonNull(changePostReqVO.getNewPostLevel())) {
            PostLevelRespDTO level = postLevelServiceProvider.getPostLevel(changePostReqVO.getNewPostLevel());
            if (Objects.isNull(level) || !level.getPostId().equals(changePostReqVO.getNewPostId())) {
                throw exception(EMPLOYEE_POSTLEVEL_INCORRECT);
            }
        }

        // 获取岗位信息
        List<Long> postIds = Stream.of(changePostReqVO.getNewDeptId(), changePostReqVO.getNewPostId()).collect(Collectors.toList());
        Map<Long, PostRespDTO> postMap = postServiceProvider.getPostMap(postIds);
        String oldPostName = Objects.nonNull(postMap.get(changePostReqVO.getOldPostId())) ? postMap.get(changePostReqVO.getOldPostId()).getName() : null;
        String newPostName = Objects.nonNull(postMap.get(changePostReqVO.getNewPostId())) ? postMap.get(changePostReqVO.getNewPostId()).getName() : null;
        // 获取部门信息
        List<Long> deptIds = Stream.of(changePostReqVO.getNewDeptId(), changePostReqVO.getOldDeptId()).collect(Collectors.toList());
        Map<Long, DeptRespDTO> deptMap = deptServiceProvider.getDeptMap(deptIds);
        String oldDeptName = Objects.nonNull(deptMap.get(changePostReqVO.getOldDeptId())) ? deptMap.get(changePostReqVO.getOldDeptId()).getName() : null;
        String newDeptName = Objects.nonNull(deptMap.get(changePostReqVO.getOldDeptId())) ? deptMap.get(changePostReqVO.getOldDeptId()).getName() : null;

        // 获取岗级信息
        List<Long> postLevelIds = Stream.of(changePostReqVO.getNewPostLevel(), changePostReqVO.getOldPostLevel()).collect(Collectors.toList());
        Map<Long, PostLevelRespDTO> postLevelMap = postLevelServiceProvider.getPostLevelMap(postLevelIds);
        String oldPostLevelName = Objects.nonNull(postLevelMap.get(changePostReqVO.getOldPostLevel())) ? postLevelMap.get(changePostReqVO.getOldPostLevel()).getName() : null;
        String newPostLevelName = Objects.nonNull(postLevelMap.get(changePostReqVO.getNewPostLevel())) ? postLevelMap.get(changePostReqVO.getNewPostLevel()).getName() : null;

        // 获取当前登录人
        AdminUserRespDTO loginUser = adminUserServiceProvider.getLoginUser();
        // 日志相关
        StringBuilder action = new StringBuilder(loginUser.getNickname() + "  为" + employeeDO.getName() + "添加了一条人事异动");
        StringBuilder actionType = new StringBuilder();

        // 成长轨迹
        EmployeeGrowthRecordSaveReqVO vo = new EmployeeGrowthRecordSaveReqVO();
        vo.setEmployeeId(employeeId);

        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        // 调岗
        if (ChangeTypeEnum.CHANGE_POST.getCode().equals(changePostReqVO.getChangeType())) {
            createFileRefList(changePostReqVO.getApplyFileIdList(), BizFileTypeEnum.TRANSFER_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(changePostReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_CHANGEPOST.getCode(), fileRefList);
            actionType.append("【调岗】");
            vo.setContent(EmployeeGrowthEnum.EMPLOYEE_TRANSFER_JOB_TRANSFER.getAction());
            vo.setAction("用户" + employeeDO.getName() + "调岗审核通过");

        }
        // 晋升
        else if (ChangeTypeEnum.PROMOTED.getCode().equals(changePostReqVO.getChangeType())) {
            createFileRefList(changePostReqVO.getApplyFileIdList(), BizFileTypeEnum.PROMOTION_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(changePostReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_PROMOTED.getCode(), fileRefList);
            vo.setContent(EmployeeGrowthEnum.EMPLOYEE_TRANSFER_PROMOTION.getAction());
            vo.setAction("用户" + employeeDO.getName() + "晋升审核通过");
        }
        // 降级
        else if (ChangeTypeEnum.DEGRADE.getCode().equals(changePostReqVO.getChangeType())) {
            createFileRefList(changePostReqVO.getApplyFileIdList(), BizFileTypeEnum.DOWNGRADE_APPLICATION_FORM.getCode(), fileRefList);
            createFileRefList(changePostReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_IN_SERVICE_DEGRADE.getCode(), fileRefList);
            vo.setContent(EmployeeGrowthEnum.EMPLOYEE_TRANSFER_DOWNGRADING.getAction());
            vo.setAction("用户" + employeeDO.getName() + "降级审核通过");
        }
        String actionEnd = "，异动原因：" + ChangeReasonEnum.getName(changePostReqVO.getChangeReason()) + "，生效日期：" + changePostReqVO.getEffectTime()
                + ",部门由" + oldDeptName + "变更为" + newDeptName + ",岗位由" + oldPostName + "变更为" + newPostName + ",岗级由"
                + oldPostLevelName + "变更为" + newPostLevelName;
        action.append(actionType).append(actionEnd);

        // 插入成长轨迹
        vo.setEffectiveTime(changePostReqVO.getEffectTime());
        employeeGrowthRecordService.createEmployeeGrowthRecord(vo);

        // 插入调动记录
        EmployeeTransferRecordDO recordDO = BeanUtils.toBean(changePostReqVO, EmployeeTransferRecordDO.class);
        recordDO.setApproveResult(BpmProcessInstanceStatusEnum.APPROVE.getStatus());
        recordDO.setCreateType(EmployeeRecordTypeEnum.Management.getType());
        employeeTransferRecordService.createEmployeeChangeRecord(recordDO);

        // 如果生效时间在当前时间之前（包含），则调动直接生效
        boolean changePost = changePostReqVO.getEffectTime().isBefore(LocalDateTime.now()) || changePostReqVO.getEffectTime().compareTo(LocalDateTime.now()) == 0;

        if (changePost) {
            employeeDO.setPostId(Objects.nonNull(changePostReqVO.getNewPostId()) ? changePostReqVO.getNewPostId() : employeeDO.getPostId());
            employeeDO.setDeptId(Objects.nonNull(changePostReqVO.getNewDeptId()) ? changePostReqVO.getNewDeptId() : employeeDO.getDeptId());
            employeeDO.setPostLevelId(Objects.nonNull(changePostReqVO.getNewPostLevel()) ? changePostReqVO.getNewPostLevel() : employeeDO.getPostLevelId());
        }

        employeeMapper.updateById(employeeDO);

        // 插入日志相关话术
        OperationLogUtils.setOperationInfo(employeeId, Collections.singletonMap("info", action));

        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_CHANGE_POST.getValue(), recordDO.getId());

        // 如果生效时间在当前时间之前（包含），则调动直接生效
        if (changePost) {
            // 风险扫描
            // 调岗
            if (ChangeTypeEnum.CHANGE_POST.getCode().equals(recordDO.getChangeType())) {
                employeeRiskHandleService.execute(Collections.singleton(employeeDO.getId()), RiskTypeEnum.TRANSFER_APPLICATION_FORM.getCode());
            }
            // 降级
            if (ChangeTypeEnum.DEGRADE.getCode().equals(recordDO.getChangeType())) {
                employeeRiskHandleService.execute(Collections.singleton(employeeDO.getId()), RiskTypeEnum.DEMOTION_NOTICE_FORM.getCode());
            }
            // 人事异动时，检查规章制度制定及实施风险
            changePostForRegulationRisk(employeeDO);
            // 更新部门
            riskService.changeEmpRiskDept(employeeDO.getId(), employeeDO.getDeptId());
            // 如有，更新用户信息
            if (employeeDO.getUserId() != null) {
                EmployeeLoginInfoSaveReqVO reqVO = BeanUtils.toBean(employeeDO, EmployeeLoginInfoSaveReqVO.class);
                reqVO.setId(employeeDO.getUserId());
                reqVO.setEmployeeId(employeeDO.getId());
                reqVO.setPassword(null);
                updateUserInfo(reqVO, employeeDO);
            }
        }
    }

    @Override
    public EmployeeLeaveRespVO getEmployeeLeave(Long id) {
        EmployeeSeparationRecordDO separationRecord = separationRecordService.getEmployeeSeparationRecord(id);
        if (Objects.isNull(separationRecord)) {
            throw exception(EMPLOYEE_SEPARATION_INFO_NOT_EXISTS);
        }
        EmployeeBasicInfoRespVo employeeInfo = getEmployeeInfo(separationRecord.getEmployeeId());
        EmployeeLeaveRespVO respVO = BeanUtils.toBean(employeeInfo, EmployeeLeaveRespVO.class);
        respVO.setApproveResult(separationRecord.getApproveResult());
        respVO.setApproveResult(separationRecord.getApproveResult());
        respVO.setSeparationType(SeparationTypeEnum.getDesc(separationRecord.getSeparationType()));
        respVO.setSeparationReason(SeparationReasonEnum.getDesc(separationRecord.getSeparationReason()));
        respVO.setSeparationTime(separationRecord.getSeparationTime());
        respVO.setApplySeparationTime(separationRecord.getApplySeparationTime());
        respVO.setRemarks(separationRecord.getRemarks());
        respVO.setCreateTime(separationRecord.getCreateTime());


        // 附件相关
        List<Integer> bizFileType = Stream.of(BizFileTypeEnum.SEPARATION_APPLICATION_FORM.getCode(), BizFileTypeEnum.SEPARATION_COMMITMENT.getCode(),
                BizFileTypeEnum.SEPARATION_AGREEMENT.getCode(), BizFileTypeEnum.OTHER_SEPARATION_MATERIALS.getCode()
                , BizFileTypeEnum.WORK_HANDOVER.getCode()).collect(Collectors.toList());
        FileRefQueryDTO refQueryDTO = new FileRefQueryDTO();
        refQueryDTO.setBizType(BizTypeEnum.EMPLOYEE_LEAVE.getValue());
        refQueryDTO.setBizFileTypes(bizFileType);
        refQueryDTO.setBizRecordIds(Arrays.asList(separationRecord.getId()));
        List<FileRefRespDTO> fileList = fileServiceProvider.getFileRef(refQueryDTO);
        if (CollUtil.isNotEmpty(fileList)) {
            Map<Integer, List<FileRefRespDTO>> map = fileList.stream().collect(Collectors.groupingBy(FileRefRespDTO::getBizFileType));
            // 离职申请表
            respVO.setApplyFileIdList(map.get(BizFileTypeEnum.SEPARATION_APPLICATION_FORM.getCode()));
            // 离职承诺书
            respVO.setCommitFileIdList(map.get(BizFileTypeEnum.SEPARATION_COMMITMENT.getCode()));
            // 离职协议
            respVO.setProtocolFileIdList(map.get(BizFileTypeEnum.SEPARATION_AGREEMENT.getCode()));
            // 其他附件
            respVO.setOtherFileIdList(map.get(BizFileTypeEnum.OTHER_SEPARATION_MATERIALS.getCode()));
        }
        return respVO;
    }

    @Override
    public EmployeeBasicInfoRespVo validateLeave() {
        Long employeeId = EmployeeContextHolder.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO.getState().equals(EmployeeStatusEnum.TO_BE_SEPARATED.getCode())) {
            throw exception(EMPLOYEE_SEPARATION_INFO_EXISTING);
        }
        return getEmployeeInfo(employeeId);
    }


    @Override
    public BpmProcessTemplatesDTO validateLeaveNew(String type, Integer tgType) {
        Long employeeId = EmployeeContextHolder.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO.getState().equals(EmployeeStatusEnum.TO_BE_SEPARATED.getCode())) {
            throw exception(EMPLOYEE_SEPARATION_INFO_EXISTING);
        }
        CommonResult<BpmProcessTemplatesDTO> result = bpmNewApi.processDetail(type, tgType);
        return result.getData();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.RESIGNATION)
    public void employeeLeave(EmployeeLeaveReqVO leaveReqVO) {
        Long employeeId = leaveReqVO.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        if (EmployeeStatusEnum.SEPARATED.getCode().equals(employeeDO.getState())
                || EmployeeStatusEnum.TO_BE_SEPARATED.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_LEAVE);
        }

        // 附件相关
        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        // 添加附件关联关系
        createFileRefList(leaveReqVO.getApplyFileIdList(), BizFileTypeEnum.SEPARATION_APPLICATION_FORM.getCode(), fileRefList);
        createFileRefList(leaveReqVO.getCommitFileIdList(), BizFileTypeEnum.SEPARATION_COMMITMENT.getCode(), fileRefList);
        createFileRefList(leaveReqVO.getProtocolFileIdList(), BizFileTypeEnum.SEPARATION_AGREEMENT.getCode(), fileRefList);
        createFileRefList(leaveReqVO.getWorkHandoverFileIdList(), BizFileTypeEnum.WORK_HANDOVER.getCode(), fileRefList);
        createFileRefList(leaveReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_SEPARATION_MATERIALS.getCode(), fileRefList);

        // 添加离职记录
        leaveReqVO.setCreateType(EmployeeRecordTypeEnum.EMPLOYEE.getType());
        Long recordId = separationRecordService.createEmployeeSeparationRecord(leaveReqVO);

        // 审批相关
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();

        String processInstanceId = bpmServiceProvider.createProcessInstance(
                new BpmProcessInstanceCreateReqDTO()
                        .setProcessDefinitionKey(ProcessDefinitionEnum.SEPARATION.getKey())
                        .setVariables(processInstanceVariables)
                        .setBusinessKey(recordId.toString())
        );

        leaveReqVO.setId(recordId);
        leaveReqVO.setApproveResult(BpmProcessInstanceStatusEnum.RUNNING.getStatus());
        leaveReqVO.setApproveProcessInstanceId(processInstanceId);
        leaveReqVO.setOldStatus(employeeDO.getState());
        leaveReqVO.setApplySeparationTime(LocalDateTime.now());
        separationRecordService.updateEmployeeSeparationRecord(leaveReqVO);

        employeeDO.setState(EmployeeStatusEnum.TO_BE_SEPARATED.getCode());
        employeeDO.setApplySeparationTime(LocalDateTime.now());
        employeeDO.setPlanSeparationTime(leaveReqVO.getSeparationTime());
        employeeDO.setSeparationRemarks(leaveReqVO.getRemarks());
        employeeDO.setSeparationType(leaveReqVO.getSeparationType());
        employeeDO.setSeparationReason(leaveReqVO.getSeparationReason());
        employeeMapper.updateById(employeeDO);

        // 员工端提交申请时，附件关联审批记录id
        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_LEAVE.getValue(), recordId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.RESIGNATION)
    public void employeeLeaveNew(StartProcessInstanceDTO param) {

        Long employeeId = param.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        if (EmployeeStatusEnum.SEPARATED.getCode().equals(employeeDO.getState())
                || EmployeeStatusEnum.TO_BE_SEPARATED.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_LEAVE);
        }

        com.alibaba.fastjson2.JSONObject formData = param.getFormData();

        String separationTypeKey = formData.getString("lz_separation_type");
        CommonResult<DictDataRespDTO> dictDataRespDTOCommonResult = dictDataApi.parseDictData("hrm_separation_type", separationTypeKey);
        String separationTypeValue = dictDataRespDTOCommonResult.getData().getValue();

        String separationReasonKey = formData.getString("lz_separation_reason");
        CommonResult<DictDataRespDTO> dictDataRespDTOCommonResult1 = dictDataApi.parseDictData("hrm_separation_reason", separationReasonKey);
        String separationReasonValue = dictDataRespDTOCommonResult1.getData().getValue();

        String separationTimeValue = formData.getString("lz_separation_time");

        List<FileUploadDTO> applyFileValue = formData.getList("lz_apply_file", FileUploadDTO.class);
        List<Long> applyFileIdList = applyFileValue != null ? applyFileValue.stream().map(FileUploadDTO::getId).collect(Collectors.toList()) : null;

        List<FileUploadDTO> commitFileValue = formData.getList("lz_commit_file", FileUploadDTO.class);
        List<Long> commitFileIdList = commitFileValue != null ? commitFileValue.stream().map(FileUploadDTO::getId).collect(Collectors.toList()) : null;

        List<FileUploadDTO> otherFileValue = formData.getList("lz_other_file", FileUploadDTO.class);
        List<Long> otherFileIdList = otherFileValue != null ? otherFileValue.stream().map(FileUploadDTO::getId).collect(Collectors.toList()) : null;

        String remarksValue = formData.getString("lz_remarks");


        EmployeeLeaveReqVO req = new EmployeeLeaveReqVO();
        req.setEmployeeId(param.getEmployeeId());
        req.setSeparationType(Integer.valueOf(separationTypeValue));
        req.setSeparationReason(Integer.valueOf(separationReasonValue));
        req.setSeparationTime(LocalDateTime.parse(separationTimeValue + " 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        req.setApplyFileIdList(applyFileIdList);
        req.setCommitFileIdList(commitFileIdList);
        req.setOtherFileIdList(otherFileIdList);
        req.setRemarks(remarksValue);

        // 附件相关
        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        // 添加附件关联关系
        createFileRefList(req.getApplyFileIdList(), BizFileTypeEnum.SEPARATION_APPLICATION_FORM.getCode(), fileRefList);
        createFileRefList(req.getCommitFileIdList(), BizFileTypeEnum.SEPARATION_COMMITMENT.getCode(), fileRefList);
        createFileRefList(req.getProtocolFileIdList(), BizFileTypeEnum.SEPARATION_AGREEMENT.getCode(), fileRefList);
        createFileRefList(req.getWorkHandoverFileIdList(), BizFileTypeEnum.WORK_HANDOVER.getCode(), fileRefList);
        createFileRefList(req.getOtherFileIdList(), BizFileTypeEnum.OTHER_SEPARATION_MATERIALS.getCode(), fileRefList);

        // 添加离职记录
        req.setCreateType(EmployeeRecordTypeEnum.EMPLOYEE.getType());
        Long recordId = separationRecordService.createEmployeeSeparationRecord(req);
        param.setBusinessId(recordId.toString());

        // 发起审批
        CommonResult<Object> result = bpmNewApi.processStart(param);
        String processInstanceId = result.getData().toString();

        req.setId(recordId);
        req.setApproveResult(BpmProcessInstanceStatusEnum.RUNNING.getStatus());
        req.setApproveProcessInstanceId(processInstanceId);
        req.setOldStatus(employeeDO.getState());
        req.setApplySeparationTime(LocalDateTime.now());
        separationRecordService.updateEmployeeSeparationRecord(req);

        employeeDO.setState(EmployeeStatusEnum.TO_BE_SEPARATED.getCode());
        employeeDO.setApplySeparationTime(LocalDateTime.now());
        employeeDO.setPlanSeparationTime(req.getSeparationTime());
        employeeDO.setSeparationRemarks(req.getRemarks());
        employeeDO.setSeparationType(req.getSeparationType());
        employeeDO.setSeparationReason(req.getSeparationReason());
        employeeMapper.updateById(employeeDO);

        // 员工端提交申请时，附件关联审批记录id
        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_LEAVE.getValue(), recordId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.RESIGNATION)
    public void rejectLeave(Long id, Integer approveResult) {
        EmployeeSeparationRecordDO separationRecord = separationRecordService.getEmployeeSeparationRecord(id);
        if (Objects.isNull(separationRecord)) {
            throw exception(EMPLOYEE_SEPARATION_INFO_NOT_EXISTS);
        }
        EmployeeDO employeeDO = employeeMapper.selectById(separationRecord.getEmployeeId());
        if (Objects.isNull(employeeDO)) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        employeeDO.setState(separationRecord.getOldStatus());
        employeeMapper.updateById(employeeDO);

        separationRecord.setApproveResult(approveResult);
        separationRecordService.updateEmployeeSeparation(separationRecord);

        employeeDO.setState(separationRecord.getOldEmployeeState());
        employeeMapper.updateById(employeeDO);

        // 日志相关
        String action = employeeDO.getName() + "发起的调动申请" +
                (approveResult.equals(BpmProcessInstanceStatusEnum.CANCEL.getStatus()) ? "已取消" : "已被驳回");
        OperationLogUtils.setOperationInfo(employeeDO.getId(), Collections.singletonMap("info", action));

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.RESIGNATION)
    public void approvedLeave(Long id, Integer approveResult) {
        EmployeeSeparationRecordDO separationRecord = separationRecordService.getEmployeeSeparationRecord(id);
        if (Objects.isNull(separationRecord)) {
            throw exception(EMPLOYEE_SEPARATION_INFO_NOT_EXISTS);
        }
        EmployeeDO employeeDO = employeeMapper.selectById(separationRecord.getEmployeeId());
        if (Objects.isNull(employeeDO)) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        employeeDO.setState(EmployeeStatusEnum.TO_BE_SEPARATED.getCode());
        // 如果生效时间在当前时间之前（包含），则离职直接生效
        if (employeeDO.getPlanSeparationTime().isBefore(LocalDateTime.now()) || employeeDO.getPlanSeparationTime().compareTo(LocalDateTime.now()) == 0) {
            employeeDO.setState(EmployeeStatusEnum.SEPARATED.getCode());
            disableUser(employeeDO);
        }
        employeeMapper.updateById(employeeDO);

        try {
            int year = employeeDO.getPlanSeparationTime().getYear(); // 获取年份
            int month = employeeDO.getPlanSeparationTime().getMonthValue(); // 获取月份
            ProgrammeEmployeeSaveBo programmeEmployeeSaveBo = new ProgrammeEmployeeSaveBo();
            programmeEmployeeSaveBo.setAccumulationStartTime(year + "-0" + month);
            programmeEmployeeSaveBo.setProgrammeStartTime(year + "-0" + month);
            programmeEmployeeSaveBo.setIsProgramme(1);
            programmeEmployeeSaveBo.setIsAccumulation(1);
            programmeEmployeeSaveBo.setProgrammeState(2);
            programmeEmployeeSaveBo.setEmployeeId(employeeDO.getId().intValue());
            hrmProgrammeService.insertProgrammeEmployeeStop(programmeEmployeeSaveBo);
        } catch (Exception e) {
            e.getMessage();
        }
        separationRecord.setApproveResult(approveResult);
        separationRecordService.updateEmployeeSeparation(separationRecord);

        // 日志相关
        OperationLogUtils.setOperationInfo(employeeDO.getId(), Collections.singletonMap("info", "用户" + employeeDO.getName() + "离职申请通过"));

        // 风险扫描
        List<Long> riskTypes = Stream.of(RiskTypeEnum.LEAVE_APPLICATION_FORM.getCode(), RiskTypeEnum.LEAVE_COMMITMENT_LETTER.getCode()).collect(Collectors.toList());
        employeeRiskHandle(Collections.singleton(employeeDO.getId()), riskTypes);

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog(docType = DocTypeEnum.EMPLOYEE, operateType = OperationTypeEnum.RESIGNATION)
    public void leave(EmployeeLeaveReqVO leaveReqVO) {
        Long employeeId = leaveReqVO.getEmployeeId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }
        if (EmployeeStatusEnum.SEPARATED.getCode().equals(employeeDO.getState())
                || EmployeeStatusEnum.TO_BE_SEPARATED.getCode().equals(employeeDO.getState())) {
            throw exception(EMPLOYEE_STATUS_NOT_ALLOW_LEAVE);
        }

        // 添加离职记录
        leaveReqVO.setOldStatus(employeeDO.getState());
        leaveReqVO.setCreateType(EmployeeRecordTypeEnum.Management.getType());
        leaveReqVO.setApplySeparationTime(LocalDateTime.now());
        leaveReqVO.setApproveResult(BpmProcessInstanceStatusEnum.APPROVE.getStatus());
        Long recordId = separationRecordService.createEmployeeSeparationRecord(leaveReqVO);

        employeeDO.setId(leaveReqVO.getEmployeeId());
        employeeDO.setState(EmployeeStatusEnum.TO_BE_SEPARATED.getCode());
        employeeDO.setApplySeparationTime(leaveReqVO.getApplySeparationTime());
        employeeDO.setPlanSeparationTime(leaveReqVO.getSeparationTime());
        employeeDO.setSeparationRemarks(leaveReqVO.getRemarks());
        employeeDO.setSeparationType(leaveReqVO.getSeparationType());
        employeeDO.setSeparationReason(leaveReqVO.getSeparationReason());
        // 如果生效时间在当前时间之前（包含），则离职直接生效
        if (employeeDO.getPlanSeparationTime().isBefore(LocalDateTime.now()) || employeeDO.getPlanSeparationTime().compareTo(LocalDateTime.now()) == 0) {
            employeeDO.setState(EmployeeStatusEnum.SEPARATED.getCode());
            disableUser(employeeDO);
            try {
                int year = employeeDO.getPlanSeparationTime().getYear(); // 获取年份
                int month = employeeDO.getPlanSeparationTime().getMonthValue(); // 获取月份
                ProgrammeEmployeeSaveBo programmeEmployeeSaveBo = new ProgrammeEmployeeSaveBo();
                programmeEmployeeSaveBo.setAccumulationStartTime(year + "-0" + month);
                programmeEmployeeSaveBo.setProgrammeStartTime(year + "-0" + month);
                programmeEmployeeSaveBo.setIsProgramme(1);
                programmeEmployeeSaveBo.setIsAccumulation(1);
                programmeEmployeeSaveBo.setProgrammeState(2);
                programmeEmployeeSaveBo.setEmployeeId(employeeDO.getId().intValue());
                hrmProgrammeService.insertProgrammeEmployeeStop(programmeEmployeeSaveBo);
            } catch (Exception e) {
                e.getMessage();
            }

        }
        employeeMapper.updateById(employeeDO);

        // 成长轨迹
        EmployeeGrowthRecordSaveReqVO vo = new EmployeeGrowthRecordSaveReqVO();
        vo.setEmployeeId(employeeId);
        vo.setContent(EmployeeGrowthEnum.EMPLOYEE_RESIGNATION.getAction());
        vo.setAction("用户" + employeeDO.getName() + "提交了离职");
        vo.setEffectiveTime(leaveReqVO.getSeparationTime());
        employeeGrowthRecordService.createEmployeeGrowthRecord(vo);

        // 日志相关
        OperationLogUtils.setOperationInfo(employeeId, Collections.singletonMap("info", "用户" + employeeDO.getName() + "办理了离职"));
        // 附件相关
        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        // 添加附件关联关系
        createFileRefList(leaveReqVO.getApplyFileIdList(), BizFileTypeEnum.SEPARATION_APPLICATION_FORM.getCode(), fileRefList);
        createFileRefList(leaveReqVO.getCommitFileIdList(), BizFileTypeEnum.SEPARATION_COMMITMENT.getCode(), fileRefList);
        createFileRefList(leaveReqVO.getProtocolFileIdList(), BizFileTypeEnum.SEPARATION_AGREEMENT.getCode(), fileRefList);
        createFileRefList(leaveReqVO.getWorkHandoverFileIdList(), BizFileTypeEnum.WORK_HANDOVER.getCode(), fileRefList);
        createFileRefList(leaveReqVO.getOtherFileIdList(), BizFileTypeEnum.OTHER_SEPARATION_MATERIALS.getCode(), fileRefList);
        fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, BizTypeEnum.EMPLOYEE_LEAVE.getValue(), recordId);
        // 风险扫描
        List<Long> types = Stream.of(RiskTypeEnum.LEAVE_APPLICATION_FORM.getCode(), RiskTypeEnum.LEAVE_COMMITMENT_LETTER.getCode(),
                RiskTypeEnum.LABOR_CONTRACT_TERMINATION.getCode(), RiskTypeEnum.WORK_HANDOVER_FORM.getCode()).collect(Collectors.toList());
        employeeRiskHandle(Collections.singleton(employeeId), types);
    }


    // @Override
    // public void cancelLeave(EmployeeCancelLeaveReqVO cancelLeaveReqVO) {
    //
    // }

    private void createFileRefList(List<Long> fileIdList, Integer
            bizFileType, List<FileRefSaveBaseDTO> fileRefList) {
        if (CollUtil.isEmpty(fileIdList)) {
            return;
        }
        for (Long fileId : fileIdList) {
            FileRefSaveBaseDTO dto = new FileRefSaveBaseDTO();
            dto.setFileId(fileId);
            dto.setBizFileType(bizFileType);
            fileRefList.add(dto);
        }
    }

    @Override
    public boolean createEmployeeFileRef(EmployeeFileReqVo vo) {
        List<FileRefSaveBaseDTO> fileRefList = new ArrayList<>();
        FileRefSaveBaseDTO dto = new FileRefSaveBaseDTO();
        dto.setFileId(vo.getFileId());
        dto.setBizFileType(vo.getBizFileType());
        boolean[] bitTagArr = new boolean[1];
        bitTagArr[0] = true;
        dto.setBitTagArr(bitTagArr);
        fileRefList.add(dto);
        Boolean result = fileServiceProvider.createFileRefByBizTypeAndRecordId(fileRefList, vo.getBizType(), vo.getRecordId());
        // 风险点检查
        employeeRiskHandleChainService.execute(Collections.singleton(vo.getRecordId()));
        return result;
    }

    @Async
    public void employeeRiskHandle(Set<Long> employeeIdList, Collection<Long> riskType) {
        if (CollUtil.isNotEmpty(employeeIdList) && CollUtil.isNotEmpty(riskType)) {
            for (Long type : riskType) {
                employeeRiskHandleService.execute(employeeIdList, type);
            }
        }
    }


    @Override
    public PageResult<EmployeeLogRespVO> getEmployeeActionLog(EmployeeLogReqVO logReqVO) {
        PageResult<EmployeeLogRespVO> result = new PageResult<>();
        OperationLogPageReqVO reqVO = new OperationLogPageReqVO();
        reqVO.setCode(logReqVO.getEmployeeId());
        PageResult<OperationLogRespVO> logPage = operationLogService.getOperateLogPage(reqVO);
        if (logPage.getTotal() > 0) {
            List<EmployeeLogRespVO> employeeLogRespVOS = CollectionUtils.convertList(logPage.getList(), l -> {
                EmployeeLogRespVO vo = new EmployeeLogRespVO();
                vo.setId(l.getId());
                vo.setAction(l.getAction());
                vo.setOperator(l.getOperator());
                vo.setCreateTime(l.getCreateTime());
                vo.setOperatorName(l.getOperatorName());
                return vo;
            });
            result.setTotal(logPage.getTotal());
            result.setList(employeeLogRespVOS);
        }

        return result;
    }

    @Override
    public List<EmployeeStatusCountRespVO> countStatusNum(EmployeePageReqVO pageReqVO) {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        pageReqVO.setState(null);
        List<EmployeeDO> employeeList = employeeMapper.selectPage(pageReqVO).getList();
        List<EmployeeStatusCountRespVO> respVOS = new ArrayList<>();
        int[] arrays = EmployeeStatusEnum.ARRAYS;
        for (int i : arrays) {
            EmployeeStatusCountRespVO vo = new EmployeeStatusCountRespVO();
            vo.setStatus(i);
            vo.setCount(CollUtil.isEmpty(employeeList) ? 0 : employeeList.stream().filter(e -> e.getState().equals(i)).count());
            respVOS.add(vo);
        }
        return respVOS;
    }

    // 获取各状态员工数量
    public List<EmployeeStatusCountRespVO> getStatusCountList() {
        // 当前租户所有员工
        List<EmployeeDO> employeeList = employeeMapper.selectList();

        List<EmployeeStatusCountRespVO> respVOS = new ArrayList<>();

        int[] arrays = EmployeeStatusEnum.ARRAYS;
        for (int i : arrays) {
            EmployeeStatusCountRespVO vo = new EmployeeStatusCountRespVO();
            vo.setStatus(i);
            vo.setCount(employeeList.stream().filter(e -> e.getState().equals(i)).count());
            respVOS.add(vo);
        }
        return respVOS;
    }

    @Override
    public void addFile(EmployeeAddFileReqVO addFileReqVO) {
        FileRefSaveBaseDTO saveBaseDTO = new FileRefSaveBaseDTO();
        saveBaseDTO.setFileId(addFileReqVO.getFileId());
        saveBaseDTO.setBizFileType(addFileReqVO.getFileType());

        fileServiceProvider.createFileRefByBizTypeAndRecordId(
                Collections.singletonList(saveBaseDTO),
                BizTypeEnum.EMPLOYEE.getValue(),
                addFileReqVO.getEmployeeId()
        );
    }

    @Override
    public List<FileRefRespDTO> getFileListByFileType(EmployeeAddFileReqVO addFileReqVO) {
        FileRefQueryDTO fileRefQueryDTO = new FileRefQueryDTO();
        fileRefQueryDTO.setBizType(BizTypeEnum.EMPLOYEE.getValue());
        fileRefQueryDTO.setBizFileTypes(Collections.singletonList(addFileReqVO.getFileType()));
        fileRefQueryDTO.setBizRecordIds(Collections.singletonList(addFileReqVO.getEmployeeId()));

        return fileServiceProvider.getFileRef(fileRefQueryDTO);
    }

    @Override
    public List<EmployeeQueryRespBo> getEmployeeQueryRespBo(Collection<Long> ids) {
        List<EmployeeDO> employeeList = getEmployeeList(ids);
        if (CollUtil.isEmpty(employeeList)) {
            return Collections.emptyList();
        }
        List<Long> postIds = employeeList.stream().map(EmployeeDO::getPostId).collect(Collectors.toList());
        List<Long> deptIds = employeeList.stream().map(EmployeeDO::getDeptId).collect(Collectors.toList());

        Map<Long, PostRespDTO> postMap = postServiceProvider.getPostMap(postIds);
        Map<Long, DeptRespDTO> deptMap = deptServiceProvider.getDeptMap(deptIds);

        return CollectionUtils.convertList(employeeList, e -> {
            EmployeeQueryRespBo respBo = new EmployeeQueryRespBo();
            respBo.setEmployeeId(e.getId());
            respBo.setEmployeeName(e.getName());
            respBo.setDeptId(e.getDeptId());
            if (Objects.nonNull(deptMap.get(e.getDeptId()))) {
                respBo.setDeptName(deptMap.get(e.getDeptId()).getName());
            }
            if (Objects.nonNull(e.getPostId())) {
                respBo.setPostId(e.getPostId());
            }
            if (Objects.nonNull(postMap.get(e.getPostId()))) {
                respBo.setPostName(postMap.get(e.getPostId()).getName());
            }
            respBo.setEmployeeNo(e.getEmployeeNo());
            return respBo;
        });

    }

    @Override
    public void updateEmployeeStatus(EmployeeUpdateStatusReqVO updateStatusReqVO) {
        Long employeeId = updateStatusReqVO.getId();
        EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
        if (employeeDO == null) {
            throw exception(EMPLOYEE_NOT_EXISTS);
        }

        EmployeeDO updateObj = new EmployeeDO();
        updateObj.setId(employeeId);
        updateObj.setState(updateStatusReqVO.getState());

        employeeMapper.updateById(updateObj);
    }

    /**
     * 构建返回前端的附件样式
     *
     * @param fileTypeList 附件类型 {@link  BizFileTypeEnum}
     * @return
     */
    public List<EmployeeFileRefBo> curdEmployeeFileRef(List<Integer> fileTypeList) {
        return CollectionUtils.convertList(fileTypeList, f -> {
            EmployeeFileRefBo refBo = new EmployeeFileRefBo();
            if (BizFileTypeEnum.isShow(f)) {
                refBo.setBizFileType(f);
                refBo.setBizType(BizTypeEnum.EMPLOYEE.getValue());
                refBo.setIcon(BizFileTypeEnum.getIconByCOde(f));
                refBo.setName(BizFileTypeEnum.getName(f));
                refBo.setIsChange(false);
                return refBo;
            }
            return null;
        });
    }

    /**
     * 给返回前端的资料列表赋值
     *
     * @param list     返回的模板
     * @param fileList 文件
     */
    public void putFileRef(List<EmployeeFileRefBo> list, List<FileRefRespDTO> fileList) {
        list.forEach(r -> {
            r.setCount(0);
            List<FileRefRespDTO> collect = fileList.stream().filter(f -> f.getBizFileType().equals(r.getBizFileType())).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect)) {
                r.setCount(collect.size());
                r.setRefRespDTOList(collect);
            }
            r.setName(BizFileTypeEnum.getName(r.getBizFileType()));
            // 单独处理在职相关其他附件
            if (BizFileTypeEnum.OTHER_IN_SERVICE_EMPLOYEES.getCode().equals(r.getBizFileType())) {
                List<Integer> onTheJob = Stream.of(BizFileTypeEnum.OTHER_IN_SERVICE_CONTRACT.getCode(),
                        BizFileTypeEnum.OTHER_IN_SERVICE_REGULARIZE.getCode(),
                        BizFileTypeEnum.OTHER_IN_SERVICE_CHANGEPOST.getCode(),
                        BizFileTypeEnum.OTHER_IN_SERVICE_PROMOTED.getCode(),
                        BizFileTypeEnum.OTHER_IN_SERVICE_DEGRADE.getCode()).collect(Collectors.toList());
                List<FileRefRespDTO> others = fileList.stream().filter(o -> onTheJob.contains(o.getBizFileType())).collect(Collectors.toList());
                collect.addAll(others);
                r.setRefRespDTOList(collect);
                if (CollUtil.isNotEmpty(r.getRefRespDTOList())) {
                    r.setName(r.getName());
                    r.setCount(r.getRefRespDTOList().size());
                }
            }
        });
    }

    // 管理端员工资料

    @Override
    public List<EmployeeFileRespBo> employeeFiles(Long id, Boolean isAdmin) {
        // 返回前端的list
        List<EmployeeFileRespBo> result = new ArrayList<>();
        EmployeeStageFileEnum[] values = EmployeeStageFileEnum.values();
        for (EmployeeStageFileEnum e : values) {
            List<FileRefRespDTO> fileList = new ArrayList<>();
            // 返回实体
            EmployeeFileRespBo respBo = new EmployeeFileRespBo();

            // 在职
            if (EmployeeStageFileEnum.EMPLOYEE_ON_THE_JOB.getCode().equals(e.getCode())) {
                respBo.setStage(EmployeeStageFileEnum.EMPLOYEE_ON_THE_JOB.getCode());
                respBo.setStageName(EmployeeStageFileEnum.getName(EmployeeStageFileEnum.EMPLOYEE_ON_THE_JOB.getCode()));
                // 员工在职期间的所有文件类型
                List<Integer> onTheJobFileType = BizFileTypeEnum.getCodeByType(EmployeeStageFileEnum.EMPLOYEE_ON_THE_JOB.getCode());
                // 构建在职阶段返回前端的模板
                List<EmployeeFileRefBo> bos = curdEmployeeFileRef(onTheJobFileType);
                // 转正附件  只保留审批通过和管理端提交的调动记录
                List<EmployeeRegularizeRecordDO> regularizeList = regularizeRecordService.getRegularizeRecordList(id).stream().filter(r ->
                        r.getApproveResult().equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus())
                                || r.getCreateType().equals(EmployeeRecordTypeEnum.Management.getType())).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(regularizeList)) {
                    List<Long> regularizeIds = CollectionUtils.convertList(regularizeList, EmployeeRegularizeRecordDO::getId);
                    fileList.addAll(getEmployeeFileList(BizTypeEnum.EMPLOYEE_REGULARIZED.getValue(), onTheJobFileType, regularizeIds));

                }
                // 调动附件  只保留审批通过和管理端提交的调动记录
                List<EmployeeTransferRecordDO> transferRecordList = employeeTransferRecordService.getTransferRecordList(id).stream().filter(t ->
                        t.getApproveResult().equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus())
                                || t.getCreateType().equals(EmployeeRecordTypeEnum.Management.getType())).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(transferRecordList)) {
                    List<Long> transferIds = CollectionUtils.convertList(transferRecordList, EmployeeTransferRecordDO::getId);
                    fileList.addAll(getEmployeeFileList(BizTypeEnum.EMPLOYEE_CHANGE_POST.getValue(), onTheJobFileType, transferIds));
                }
                // 其他在职期间的附件
                fileList.addAll(getEmployeeFileList(BizTypeEnum.EMPLOYEE.getValue(), onTheJobFileType, Collections.singletonList(id)));
                // 构建附件
                if (CollUtil.isNotEmpty(fileList)) {
                    putFileRef(bos, fileList);
                }
                // 员工端人事异动的其他附件，归类到异动类型本身
                for (EmployeeFileRefBo bo : bos) {
                    // 转正
                    if (bo.getBizFileType().equals(BizFileTypeEnum.PROBATION_ASSESSMENT_FORM.getCode())) {
                        curdOtherFiles(bo, fileList, BizFileTypeEnum.OTHER_IN_SERVICE_REGULARIZE.getCode());
                    }
                    // 晋升
                    if (bo.getBizFileType().equals(BizFileTypeEnum.PROMOTION_APPLICATION_FORM.getCode())) {
                        curdOtherFiles(bo, fileList, BizFileTypeEnum.OTHER_IN_SERVICE_PROMOTED.getCode());
                        curdOtherFiles(bo, fileList, BizFileTypeEnum.PROMOTION_APPLICATION_FORM_ADMIN.getCode());
                        bo.setIsChange(true);
                    }
                    // 调岗
                    if (bo.getBizFileType().equals(BizFileTypeEnum.TRANSFER_APPLICATION_FORM.getCode())) {
                        curdOtherFiles(bo, fileList, BizFileTypeEnum.OTHER_IN_SERVICE_CHANGEPOST.getCode());
                        curdOtherFiles(bo, fileList, BizFileTypeEnum.TRANSFER_APPLICATION_FORM_ADMIN.getCode());
                        bo.setIsChange(true);
                    }
                    // 降级
                    if (bo.getBizFileType().equals(BizFileTypeEnum.DOWNGRADE_APPLICATION_FORM.getCode())) {
                        curdOtherFiles(bo, fileList, BizFileTypeEnum.OTHER_IN_SERVICE_DEGRADE.getCode());
                        curdOtherFiles(bo, fileList, BizFileTypeEnum.DOWNGRADE_APPLICATION_FORM_ADMIN.getCode());
                        bo.setIsChange(true);
                    }
                }
                if (!isAdmin) {
                    // 员工端不展示以下
                    List<Integer> types = Stream.of(BizFileTypeEnum.CONTRACT_IN_SERVICE.getCode(), BizFileTypeEnum.CORRECTION_APPLICATION_FORM.getCode(),
                            BizFileTypeEnum.POSITION_CONFIRMATION_FORM.getCode(), BizFileTypeEnum.OTHER_IN_SERVICE_EMPLOYEES.getCode()).collect(Collectors.toList());
                    bos.removeIf(f -> types.contains(f.getBizFileType()));
                }
                respBo.setFileRefBos(bos);
                result.add(respBo);
            }
            if (EmployeeStageFileEnum.EMPLOYEE_LEAVE.getCode().equals(e.getCode())) {
                // 员工离职阶段的附件
                List<Integer> leave = BizFileTypeEnum.getCodeByType(EmployeeStageFileEnum.EMPLOYEE_LEAVE.getCode());
                // 构建在职阶段返回前端的模板
                List<EmployeeFileRefBo> bos = curdEmployeeFileRef(leave);
                // 只保留审批通过和管理端提交的调动记录
                List<EmployeeSeparationRecordDO> separatedList = separationRecordService.getSeparatedList(id).stream().filter(s ->
                        s.getApproveResult().equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus())
                                || s.getCreateType().equals(EmployeeRecordTypeEnum.Management.getType())).collect(Collectors.toList());

                if (CollUtil.isNotEmpty(separatedList)) {
                    List<Long> separated = CollectionUtils.convertList(separatedList, EmployeeSeparationRecordDO::getId);
                    fileList.addAll(getEmployeeFileList(BizTypeEnum.EMPLOYEE_LEAVE.getValue(), leave, separated));
                }
                // 离职其他
                fileList.addAll(getEmployeeFileList(BizTypeEnum.EMPLOYEE.getValue(), leave, Collections.singletonList(id)));
                respBo.setStage(EmployeeStageFileEnum.EMPLOYEE_LEAVE.getCode());
                respBo.setStageName(EmployeeStageFileEnum.getName(EmployeeStageFileEnum.EMPLOYEE_LEAVE.getCode()));

                if (CollUtil.isNotEmpty(fileList)) {
                    putFileRef(bos, fileList);
                }
                if (!isAdmin) { // 员工端只展示离职申请书和离职承诺书
                    List<Integer> collect = Stream.of(BizFileTypeEnum.SEPARATION_APPLICATION_FORM.getCode(), BizFileTypeEnum.SEPARATION_COMMITMENT.getCode()).collect(Collectors.toList());
                    bos.removeIf(f -> !collect.contains(f.getBizFileType()));
                }
                respBo.setFileRefBos(bos);

                result.add(respBo);

            }
            if (EmployeeStageFileEnum.EMPLOYEE_ENTRY.getCode().equals(e.getCode())) {
                // 员工入职相关的附件
                List<Integer> entry = BizFileTypeEnum.getCodeByType(EmployeeStageFileEnum.EMPLOYEE_ENTRY.getCode());
                // 构建在职阶段返回前端的模板
                List<EmployeeFileRefBo> bos = curdEmployeeFileRef(entry);
                fileList.addAll(getEmployeeFileList(BizTypeEnum.EMPLOYEE.getValue(), entry, Collections.singletonList(id)));

                respBo.setStage(EmployeeStageFileEnum.EMPLOYEE_ENTRY.getCode());
                respBo.setStageName(EmployeeStageFileEnum.getName(EmployeeStageFileEnum.EMPLOYEE_ENTRY.getCode()));
                if (CollUtil.isNotEmpty(fileList)) {
                    putFileRef(bos, fileList);
                }
                respBo.setFileRefBos(bos);
                if (isAdmin) { // 管理端显示入职相关
                    result.add(respBo);
                }

            }
//            if (EmployeeStageFileEnum.EMPLOYEE_EXAMINE.getCode().equals(e.getCode())) {
//                // 员工入职相关的附件
//                List<Integer> entry = BizFileTypeEnum.getCodeByType(EmployeeStageFileEnum.EMPLOYEE_EXAMINE.getCode());
//                // 构建在职阶段返回前端的模板
//                List<EmployeeFileRefBo> bos = curdEmployeeFileRef(entry);
//                fileList.addAll(getEmployeeFileList(BizTypeEnum.EMPLOYEE.getValue(), entry, Collections.singletonList(id)));
//                respBo.setStage(EmployeeStageFileEnum.EMPLOYEE_EXAMINE.getCode());
//                respBo.setStageName(EmployeeStageFileEnum.getName(EmployeeStageFileEnum.EMPLOYEE_EXAMINE.getCode()));
//                if (CollUtil.isNotEmpty(fileList)) {
//                    putFileRef(bos, fileList);
//                }
//                respBo.setFileRefBos(bos);
//                if (isAdmin) { // 管理端显示入职相关
//                    result.add(respBo);
//                }
//            }
        }
//            if (EmployeeStageFileEnum.EMPLOYEE_EXAMINE.getCode().equals(e.getCode())) {
//                // 员工入职相关的附件
//                List<Integer> entry = BizFileTypeEnum.getCodeByType(EmployeeStageFileEnum.EMPLOYEE_ENTRY.getCode());
//                // 构建在职阶段返回前端的模板
//                List<EmployeeFileRefBo> bos = curdEmployeeFileRef(entry);
//                fileList.addAll(getEmployeeFileList(BizTypeEnum.EMPLOYEE.getValue(), entry, Collections.singletonList(id)));
//
//                respBo.setStage(EmployeeStageFileEnum.EMPLOYEE_ENTRY.getCode());
//                respBo.setStageName(EmployeeStageFileEnum.getName(EmployeeStageFileEnum.EMPLOYEE_ENTRY.getCode()));
//                if (CollUtil.isNotEmpty(fileList)) {
//                    putFileRef(bos, fileList);
//                }
//                respBo.setFileRefBos(bos);
//                if (isAdmin) { // 管理端显示入职相关
//                    result.add(respBo);
//                }
//            }

//        }

        return result;
    }

    /**
     * 员工端入离转调提交的其他附件和管理端为消除风险补充的附件，合并到对应的附件中
     *
     * @param bo
     * @param fileList
     * @param type
     */
    public void curdOtherFiles(EmployeeFileRefBo bo, List<FileRefRespDTO> fileList, Integer type) {
        List<FileRefRespDTO> collect = fileList.stream().filter(o ->
                o.getBizFileType().equals(type)).collect(Collectors.toList());
        List<FileRefRespDTO> dtos = bo.getRefRespDTOList();
        if (CollUtil.isNotEmpty(collect)) {
            if (CollUtil.isEmpty(dtos)) {
                bo.setRefRespDTOList(collect);
            } else {
                dtos.addAll(collect);
                bo.setRefRespDTOList(dtos);
            }
            bo.setCount(bo.getRefRespDTOList().size());
        }
    }

    public List<FileRefRespDTO> getEmployeeFileList(Integer
                                                            bizType, Collection<Integer> bizFileType, Collection<Long> recordIds) {
        FileRefQueryDTO refQueryDTO = new FileRefQueryDTO();
        refQueryDTO.setBizFileTypes(bizFileType);
        refQueryDTO.setBizRecordIds(recordIds);
        refQueryDTO.setBizType(bizType);
        return fileServiceProvider.getFileRef(refQueryDTO);

    }

    @Override
    public List<EmployeeLeaderRespVo> getEmployeeList(String name) {
        return BeanUtils.toBean(employeeMapper.getEmployeeList(name), EmployeeLeaderRespVo.class);
    }

    @Override
    public List<EmployeeLeaderRespVo> getEmployeeList() {
        return BeanUtils.toBean(employeeMapper.getEmployeeList(), EmployeeLeaderRespVo.class);
    }

    @Override
    public PageResult<EmployeePageRespVO> getBirthdayPage(EmployeeDashboardPageReqVO pageReqVO) {
        List<EmployeeDO> employeeDOList = employeeMapper.selectList();
        List<Long> birthdayIds;
        if (Objects.nonNull(pageReqVO.getDateTime())) {
            LocalDate date = Objects.isNull(LocalDate.parse(pageReqVO.getDateTime())) ? null : LocalDate.parse(pageReqVO.getDateTime());
            birthdayIds = getBirthdayEmployeeIds(employeeDOList, date, Boolean.TRUE);
        } else {
            birthdayIds = isBirthday(employeeDOList, pageReqVO.getIsNotify());
        }
        PageResult<EmployeeDO> pageList = new PageResult<>();
        pageList.setTotal(0L);
        if (birthdayIds.size() > 0) {
            pageReqVO.setId(birthdayIds);
            pageList = employeeMapper.selectEmployeePageByIds(pageReqVO);
        }
        return curdEmployeePage(pageList);
    }

    @Override
    public PageResult<EmployeePageRespVO> getAnniversaryEmployeePage(EmployeeDashboardPageReqVO pageReqVO) {
        PageResult<EmployeePageRespVO> result = new PageResult<EmployeePageRespVO>().setList(Collections.emptyList()).setTotal(0L);
        LocalDate date = Objects.isNull(pageReqVO.getDateTime()) ? LocalDate.now() : LocalDate.parse(pageReqVO.getDateTime());
        List<EmployeeDO> employeeDOList = getEmployeeAnniversary(date);
        if (CollUtil.isNotEmpty(employeeDOList)) {
            List<Long> employeeIds = CollectionUtils.convertList(employeeDOList, EmployeeDO::getId);
            pageReqVO.setId(employeeIds);
            PageResult<EmployeeDO> pageList = new PageResult<>();
            pageList.setTotal(0L);
            pageList = employeeMapper.selectEmployeePageByIds(pageReqVO);
            return curdEmployeePage(pageList);
        }

        return result;
    }

    @Override
    public PageResult<EmployeePageRespVO> getNotifyRegularizeEmployeePage(EmployeeDashboardPageReqVO pageReqVO) {
        PageResult<EmployeePageRespVO> result = new PageResult<EmployeePageRespVO>().setList(Collections.emptyList()).setTotal(0L);
        List<EmployeeDO> employeeDOList = employeeMapper.selectList();
        employeeDOList.removeIf(e -> !e.getState().equals(EmployeeStatusEnum.PROBATION.getCode()));
        if (CollUtil.isNotEmpty(employeeDOList)) {
            List<EmployeeDO> list = CollectionUtils.convertList(employeeDOList, e -> {
                LocalDateTime planRegularizationTime = e.getEntryTime().plusMonths(e.getProbationPeriod()).minusDays(1);
                LocalDate date = Objects.isNull(pageReqVO.getDateTime()) ? LocalDate.now() : LocalDate.parse(pageReqVO.getDateTime());
                if (planRegularizationTime.toLocalDate().minusDays(7).compareTo(date) == 0) {
                    return e;
                }
                return null;
            });
            if (CollUtil.isNotEmpty(list)) {
                List<Long> ids = CollectionUtils.convertList(list, EmployeeDO::getId);
                pageReqVO.setId(ids);
                PageResult<EmployeeDO> pageList = new PageResult<>();
                pageList.setTotal(0L);
                pageList = employeeMapper.selectEmployeePageByIds(pageReqVO);
                return curdEmployeePage(pageList);
            }

        }
        return result;
    }

    @Override
    public PageResult<EmployeePageRespVO> getContractExpirationPage(EmployeeDashboardPageReqVO pageReqVO) {
        PageResult<EmployeePageRespVO> result = new PageResult<>();
        result.setList(new ArrayList<>()).setTotal(0L);
        // 获取快到期的合同
        LocalDate date = Objects.isNull(pageReqVO.getDateTime()) ? LocalDate.now() : LocalDate.parse(pageReqVO.getDateTime());
        List<EmployeeContractRespVO> contractExpiration = getContractExpiration(pageReqVO.getIsNotify(), date);
        if (CollUtil.isNotEmpty(contractExpiration)) {
            List<EmployeeDO> employeeDOList = employeeMapper.selectBatchIds(CollectionUtils.convertSet(contractExpiration, EmployeeContractRespVO::getEmployeeId));
            if (CollUtil.isNotEmpty(employeeDOList)) {
                pageReqVO.setId(CollectionUtils.convertList(contractExpiration, EmployeeContractRespVO::getId));
                pageReqVO.setEmployeeId(CollectionUtils.convertList(employeeDOList, EmployeeDO::getId));
                if (pageReqVO.getId().size() > 0) {
                    PageResult<EmployeeContractDO> pageResult = employeeContractService.selectContractExpirationPage(pageReqVO);

                    List<EmployeePageRespVO> employeeCustomField = curdEmployeeCustomFieldData(employeeDOList);
                    Map<Long, EmployeePageRespVO> map = CollectionUtils.convertMap(employeeCustomField, EmployeePageRespVO::getId);

                    List<EmployeePageRespVO> respVOList = CollectionUtils.convertList(pageResult.getList(), c -> {
                        EmployeePageRespVO vo = BeanUtils.toBean(map.get(c.getEmployeeId()), EmployeePageRespVO.class);
                        vo.setId(c.getId());
                        vo.setContractEndTime(c.getEndTime().toLocalDate());
//                        vo.setToDate(c.getEndTime().getDayOfYear() - LocalDateTime.now().getDayOfYear());
                        long ToDate = ChronoUnit.DAYS.between(LocalDate.now(), c.getEndTime().toLocalDate()) + 1;
                        vo.setToDate((int) ToDate);
                        return vo;

                    });
                    result.setTotal(pageResult.getTotal());
                    result.setList(respVOList);
                }
            }
        }
        return result;
    }

    @Override
    public EmployeeOnTheJobRespVo getOnTheJob() {
        // 各状态员工数量
        List<EmployeeStatusCountRespVO> statusCountList = getStatusCountList();
        List<EmployeeStatusEnum> collect = Arrays.stream(EmployeeStatusEnum.values()).collect(Collectors.toList());
        collect.removeIf(c -> c.getCode().equals(EmployeeStatusEnum.SEPARATED.getCode()));
        // 在职
        long onTheJob = statusCountList.stream().filter(s -> !s.getStatus().equals(EmployeeStatusEnum.SEPARATED.getCode())).mapToLong(EmployeeStatusCountRespVO::getCount).sum();
        return EmployeeOnTheJobRespVo.builder().count(onTheJob).status(CollectionUtils.convertList(collect, EmployeeStatusEnum::getCode)).build();

    }

    @Override
    public EmployeeToDoReminderRespVo getEmployeeToDoReminder() {
        EmployeeToDoReminderRespVo respVo = new EmployeeToDoReminderRespVo();

        List<EmployeeDO> employeeDOList = employeeMapper.selectList();
        List<Long> allEmployeeIds = CollectionUtils.convertList(employeeDOList, EmployeeDO::getId);

        //TODO 待薪资审核
        respVo.setSalary(0L);
        // 各状态员工数量
        List<EmployeeStatusCountRespVO> statusCountList = getStatusCountList();
        Map<Integer, EmployeeStatusCountRespVO> stateMap = CollectionUtils.convertMap(statusCountList, EmployeeStatusCountRespVO::getStatus);
        // 待转正
        respVo.setPendingRegularize(stateMap.get(EmployeeStatusEnum.PENDING_REGULARIZATION.getCode()).getCount());
        // 待离职
        respVo.setToBeSeparated(stateMap.get(EmployeeStatusEnum.TO_BE_SEPARATED.getCode()).getCount());
        // 生日提醒
        respVo.setBirthday(isBirthday(employeeDOList, false).stream().count());
        // 合同到期
        List<EmployeeContractRespVO> contractExpiration = getContractExpiration(false, LocalDate.now());

        List<Long> employeeIds = new ArrayList<>(CollectionUtils.convertMultiMap(contractExpiration, EmployeeContractRespVO::getEmployeeId).keySet());
        employeeIds.removeIf(e -> !allEmployeeIds.contains(e));
        respVo.setContractExpiration(employeeIds.stream().count());
        // TODO 其他审核
        respVo.setOtherReviews(0L);

        return respVo;
    }

    public List<EmployeeContractRespVO> getContractExpiration(Boolean isNotify, LocalDate date) {
        List<EmployeeContractRespVO> contractList = employeeContractService.selectEmployeeAllContract();
        // 去除无固定期限劳动合同
        contractList.removeIf(c -> c.getContractType().equals(EmployeeContractTypeEnum.NO_FIXED_TERM.gettype())
                || c.getContractType().equals(EmployeeContractTypeEnum.TASK_CONTRACT.gettype()));
        // 去掉已经执行完的合同 或已终止的合同
        contractList.removeIf(c -> c.getEndTime().toLocalDate().compareTo(date) < 0 || c.getTerminationStatus());
        return CollectionUtils.convertList(contractList, c -> {
            if (isNotify != null && isNotify) { // 查询消息提醒相关的合同
                if (date.plusDays(30).compareTo(c.getEndTime().toLocalDate()) == 0) {
                    return c;
                }
            } else {
                // 当前执行中或未执行的合同，60天到期的
                if (date.plusDays(60).compareTo(c.getEndTime().toLocalDate()) > 0) {
                    return c;
                }
            }
            return null;
        });
    }

    /**
     * 获取过生日的员工id
     *
     * @param employeeList 员工列表
     * @param date         指定的日期（null取当前日期）
     * @param isNotify     是否为提前7日提醒（含当天,站内信提醒用）
     * @return
     */
    public List<Long> getBirthdayEmployeeIds(List<EmployeeDO> employeeList, LocalDate date, Boolean isNotify) {
        // 只保留在职的
        employeeList.removeIf(e -> e.getState().equals(EmployeeStatusEnum.SEPARATED.getCode()));
        // 去掉生日未填写的
        employeeList.removeIf(e -> Objects.isNull(e.getBirthday()) || e.getBirthday().length() < 4);
        // 数据校验，只保留示例（0213）类型的生日格式，剔除中文和位数不够四位的
        employeeList.removeIf(e -> !e.getBirthday().substring(0, 4).matches("\\d{4}"));
        if (CollUtil.isEmpty(employeeList)) {
            return Collections.emptyList();
        }
        return CollectionUtils.convertList(employeeList, e -> {
            // 用户生日-月份
            int month = Integer.parseInt(e.getBirthday().substring(0, 2));
            // 用户生日-具体日
            int day = Integer.parseInt(e.getBirthday().substring(2, 4));

            // 判断月份,天 是否合规
            if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
                LocalDate now = Objects.isNull(date) ? LocalDate.now() : date;
                int nowMonth = now.getMonthValue();
                int nowDay = now.getDayOfMonth();
                if (e.getBirthdayType().equals(CalendarType.LUNAR.getCode())) {
                    ChineseDate chineseDate = new ChineseDate(now);
                    nowMonth = chineseDate.getMonth();
                    nowDay = chineseDate.getDay();
                }
                // 判断是否当月过生日
                if (month == nowMonth) {
                    if (isNotify != null && isNotify) {
                        // 判断是否需当天提醒
                        int birthday = day - nowDay;
                        if (birthday == 0) {
                            return e.getId();
                        }
                    } else {
                        return e.getId();
                    }
                }
            }
            return null;
        });
    }

    /**
     * 返回需要进行生日提醒的员工id集合
     *
     * @param employeeDOList 员工列表
     * @param isNotify       是否为提前7日提醒（含当天,站内信提醒用）
     * @return
     */
    public List<Long> isBirthday(List<EmployeeDO> employeeDOList, Boolean isNotify) {
        return getBirthdayEmployeeIds(employeeDOList, null, isNotify);
    }

    @Override
    public List<EmployeeOverviewRespVo> getEmployeeOverview() {
        // 各状态员工数量
        List<EmployeeStatusCountRespVO> statusCountList = getStatusCountList();
        // 按类型排序
        statusCountList.stream().sorted(Comparator.comparing(EmployeeStatusCountRespVO::getStatus));

        return CollectionUtils.convertList(statusCountList, s -> {
            EmployeeOverviewRespVo respVo = new EmployeeOverviewRespVo();
            respVo.setName(EmployeeStatusEnum.getName(s.getStatus()));
            respVo.setStatus(s.getStatus());
            respVo.setCount(s.getCount());
            return respVo;
        });
    }

    @Override
    public List<CustomFieldRespDTO> downloadExcelFiled() {
        // 获取该员工自定义字段值
        CustomFieldReqDTO dto = new CustomFieldReqDTO();
        dto.setBizType(BizTypeEnum.EMPLOYEE.getValue());
        List<CustomFieldRespDTO> dataList = customFieldServiceProvider.getFieldList(dto);
        // 添加额外字段
        CustomFieldRespDTO role = new CustomFieldRespDTO();
        role.setType(CustomFieldTypeEnum.VARCHAR.getValue());
        role.setColName("role_id");
        role.setName("角色(示例：员工通用,子管理员,主管理员...)");
        role.setIsNull(false);
        Map<Integer, List<CustomFieldRespDTO>> listMap = CollectionUtils.convertMultiMap(dataList, CustomFieldRespDTO::getType);
        List<CustomFieldRespDTO> dtos = listMap.get(CustomFieldTypeEnum.DEPT.getValue());

        if (CollUtil.isNotEmpty(dtos)) {
            role.setId(dtos.get(0).getId());
            role.setLabel(dtos.get(0).getLabel());
        } else {
            role.setId(dataList.get(dataList.size() - 1).getId());
            role.setLabel(dataList.get(dataList.size() - 1).getLabel());
        }
        dataList.add(role);
        for (CustomFieldRespDTO date : dataList) {
            fillOptions(date);
        }
        return dataList.stream().sorted(Comparator.comparing(CustomFieldRespDTO::getId)).sorted(Comparator.comparing(CustomFieldRespDTO::getLabel)).collect(Collectors.toList());

    }

    /**
     * 构建自定义字段options（目前支持岗位和部门）
     *
     * @param data
     */
    public void fillOptions(CustomFieldRespDTO data) {
        if (data.getColName().equals("post_id")) { // 岗位
            List<PostRespDTO> postList = postServiceProvider.getPostList();
            List<Map<String, Object>> listMap = new ArrayList<>();
            if (CollUtil.isNotEmpty(postList)) {
                for (PostRespDTO dto : postList) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("label", dto.getName());
                    map.put("value", dto.getId());
                    listMap.add(map);
                }
                data.setOptions(JsonUtils.toJsonString(listMap));
            }
        }
//        if (data.getColName().equals("role_id")) { // 角色
//            List<RoleRespDTO> roleList = roleServiceProvider.getAllRoleList();
//            List<Map<String, Object>> listMap = new ArrayList<>();
//            if (CollUtil.isNotEmpty(roleList)) {
//                for (RoleRespDTO dto : roleList) {
//                    Map<String, Object> map = new HashMap<>();
//                    map.put("label", dto.getName());
//                    map.put("value", dto.getId());
//                    listMap.add(map);
//                }
//                data.setOptions(JsonUtils.toJsonString(listMap));
//            }
//        }
        if (data.getColName().equals("dept_id")) { // 部门
            List<DeptRespDTO> deptList = deptServiceProvider.getDeptList();
            List<Map<String, Object>> listMap = new ArrayList<>();
            if (CollUtil.isNotEmpty(deptList)) {
                for (DeptRespDTO dto : deptList) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("label", allDeptByParent(dto.getParentId(), dto.getName()));
                    map.put("value", dto.getId());

                    listMap.add(map);
                }
                data.setOptions(JsonUtils.toJsonString(listMap));

            }
        }
    }

    public String allDeptByParent(Long id, String deptNme) {
        if (id == 0) {
            return deptNme;
        }
        CommonResult<DeptRespDTO> dept = deptApi.getDept(id);
        deptNme = dept.getCheckedData().getName() + "-" + deptNme;
        return allDeptByParent(dept.getData().getParentId(), deptNme);


    }

    /**
     * 动态表头导入功能
     *
     * @param file 文件
     * @return
     */
//    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    @Override
    public EmployeeImportRespVO importExcel(MultipartFile file) throws IOException {
        // 导入后返回的信息
        EmployeeImportRespVO respVO = EmployeeImportRespVO.builder().updateNames(new ArrayList<>()).createNames(new ArrayList<>()).failureNames(new HashMap<>()).build();
        List<PostRespDTO> postList = postServiceProvider.getPostList();
        List<DeptRespDTO> deptList = deptServiceProvider.getDeptList();
        List<PostLevelRespDTO> levelList = postLevelServiceProvider.getPostLevelList();
        List<EmployeeDO> employeeList = employeeMapper.selectList();
        List<RoleRespDTO> roleList = roleServiceProvider.getAllRoleList();
        TenantRespDTO tenant = tenantServiceProvider.getCurrentTenant();
        AdminUserRespDTO loginUser = adminUserServiceProvider.getLoginUser();
        // 首先校验传入文件是否为空
        if (file == null) {
            throw exception(DATA_IS_EMPTY);
        }
        // 引入监听器（此处需注意，监听器不可被Spring管理）
        EasyExcelListener readListener = new EasyExcelListener();
        // 开始处理excel
        EasyExcelFactory.read(file.getInputStream(), readListener)
                .sheet(0)
                .headRowNumber(2)
                .doRead();
        // 获取表头（验空）
        List<Map<Integer, String>> headList = readListener.getHeadList();
        if (CollUtil.isEmpty(headList)) {
            throw exception(DATA_HEADER_IS_EMPTY);
        }
        // 获取表数据(验空)
        List<Map<Integer, String>> dataList = readListener.getDataList();
        if (CollUtil.isEmpty(dataList)) {
            throw exception(DATA_IS_EMPTY);
        }
        //获取头部,取最后一次解析的列头数据
        Map<Integer, String> excelHeadIdxNameMap = headList.get(headList.size() - 1);

        // 组装成自定义字段
        List<CustomFieldRespDTO> customFieldList = downloadExcelFiled();
        //封装数据体
        List<Map<String, String>> excelDataList = new ArrayList<Map<String, String>>();
        List<List<String>> errorData = new ArrayList<>();
        for (Map<Integer, String> dataRow : dataList) {
            HashMap<String, String> data = new HashMap<>();
            excelHeadIdxNameMap.entrySet().forEach(columnHead -> {
                data.put(columnHead.getValue(), dataRow.get(columnHead.getKey()));
            });
            int rowNum = excelDataList.indexOf(dataRow) + 3;

            // 单个员工的自定义字段
            boolean isBreak = false;
            List<EmployeeFieldSaveReqVo> list = new ArrayList<>();
            for (CustomFieldRespDTO field : customFieldList) {
//            customFieldList.forEach(field -> {
                EmployeeFieldSaveReqVo customFieldSaveBO = BeanUtils.toBean(field, EmployeeFieldSaveReqVo.class);
                customFieldSaveBO.setFieldId(field.getId());
                for (String key : data.keySet()) {
                    // 格式化
                    String name = key.replace("*", "");
                    if (name.contains("-")) {
                        name = name.substring(0, name.indexOf("-"));
                    }
                    if (name.equals(field.getName())) {
                        String value = data.get(key);
                        if (!field.getIsNull() && Objects.isNull(value)) {
                            respVO.getFailureNames().put("第" + rowNum + "行" + key, "【1001】" + EMPLOYEE_INFO_NOT_EXISTS.getMsg());
                            ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                            valueList.add(EMPLOYEE_INFO_NOT_EXISTS.getMsg());
                            errorData.add(valueList);
                            isBreak = true;
                            break;
                        }
                        customFieldSaveBO.setFieldValue(value);
                        String options = field.getOptions();
                        Map<String, String> optionsMap = new HashMap<>();
                        if (Objects.nonNull(options)) {
                            JSONArray jsonArray = new JSONArray(options);
                            for (int j = 0; j < jsonArray.size(); j++) {
                                optionsMap.put(jsonArray.getJSONObject(j).get("label", String.class), jsonArray.getJSONObject(j).get("value", String.class));
                            }
                            // 单选下拉类型赋值
                            List<Integer> types = Stream.of(CustomFieldTypeEnum.RADIO.getValue(), CustomFieldTypeEnum.SINGLE_SELECT.getValue()).collect(Collectors.toList());
                            if (types.contains(field.getType())) {
                                customFieldSaveBO.setFieldValue(optionsMap.get(value));
                            }
                        }
                    }
                }
                if (isBreak) {
                    break;
                }
                list.add(customFieldSaveBO);
            }
            if (isBreak) {
                continue;
            }

            // EmployeeDO赋值
            Map<String, Object> map = new HashMap<>();
            list.forEach(s -> {
                map.put(s.getColName(), s.getFieldValue());
            });
            // 部门
            if (Objects.nonNull(map.get("dept_id"))) {
                String deptTreeName = String.valueOf(map.get("dept_id"));
                String[] split = deptTreeName.split("-");
                List<DeptRespDTO> depts = deptList.stream().filter(d -> d.getName().endsWith(split[split.length - 1])).collect(Collectors.toList());
                if (depts != null && depts.size() > 1) {
                    List<Long> dept_2 = deptList.stream().filter(d -> d.getName().endsWith(split[split.length - 2])).map(DeptRespDTO::getId).collect(Collectors.toList());
                    depts = depts.stream().filter(d -> dept_2.contains(d.getId())).collect(Collectors.toList());
                }
                if (CollUtil.isNotEmpty(depts)) {
                    map.put("dept_id", depts.get(0).getId());
                } else {
                    respVO.getFailureNames().put(StrUtil.nullToEmpty(map.get("name").toString()), "【1002】" + EMPLOYEE_DEPT_NOT_EXISTS.getMsg());
                    ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                    valueList.add(EMPLOYEE_DEPT_NOT_EXISTS.getMsg());
                    errorData.add(valueList);
                    continue;
                }
            }
            // 岗位
            if (Objects.nonNull(map.get("post_id"))) {
                List<PostRespDTO> posts = postList.stream().filter(d -> d.getName().equals(map.get("post_id"))).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(posts)) {
                    map.put("post_id", posts.get(0).getId());
                } else {
                    respVO.getFailureNames().put(StrUtil.nullToEmpty(map.get("name").toString()), "【1003】" + EMPLOYEE_POST_NOT_EXISTS.getMsg());
                    ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                    valueList.add(EMPLOYEE_POST_NOT_EXISTS.getMsg());
                    errorData.add(valueList);
                    continue;
                }
                List<PostLevelRespDTO> postLevelList = levelList.stream().filter(l -> l.getId().equals(map.get("post_id"))).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(postLevelList)) {
                    map.put("post_level_id", postLevelList.get(0).getId());
                } else {
                    map.put("post_level_id", null);
                }
            }
//            if(Objects.nonNull(""))
            // 角色
            String role = data.get("*角色(示例：员工通用,子管理员,主管理员...)");
            if (CollUtil.isEmpty(roleList)) {
                respVO.getFailureNames().put(StrUtil.nullToEmpty(SystemConstants.SYSTEM_USER_NICKNAME), "【1004】" + EMPLOYEE_SYSTEM_ROLE_NOT_EXISTS.getMsg());
                ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                valueList.add(EMPLOYEE_SYSTEM_ROLE_NOT_EXISTS.getMsg());
                errorData.add(valueList);
                break;
            }
            if (Objects.nonNull(role)) {
                map.put("role_id", null);
                List<String> roles = Arrays.asList(role.split("[,，.]"));
                List<RoleRespDTO> collect = roleList.stream().filter(r -> roles.contains(r.getName())).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(collect)) {
                    map.put("role_id", CollectionUtils.convertList(collect, RoleRespDTO::getId));
                } else {
                    respVO.getFailureNames().put(StrUtil.nullToEmpty(map.get("name").toString()), "【1005】" + EMPLOYEE_SYSTEM_ROLE_NOT_EXISTS.getMsg());
                    ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                    valueList.add(EMPLOYEE_SYSTEM_ROLE_NOT_EXISTS.getMsg());
                    errorData.add(valueList);
                    continue;
                }
            }
            // 上级
            if (Objects.nonNull(map.get("leader_id"))) {
                Map<String, List<EmployeeDO>> employeeListMap = CollectionUtils.convertMultiMap(employeeList, EmployeeDO::getName);
                List<EmployeeDO> employeeDOList = employeeListMap.get(map.get("leader_id"));
                if (CollUtil.isNotEmpty(employeeDOList)) {
                    map.put("leader_id", employeeDOList.get(0).getId());
                } else {
                    map.put("leader_id", null);
                }
            }

            EmployeeImportExcelVo importExcelVo = new EmployeeImportExcelVo();

            try {
                importExcelVo = BeanUtil.toBean(map, EmployeeImportExcelVo.class);
            } catch (Exception e) {
                e.printStackTrace();
                respVO.getFailureNames().put("第" + rowNum + "行" + map.get("name").toString(), "【1006】" + "员工导入数据不正确，请按照示例填写");
                ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                valueList.add("员工导入数据不正确，请按照示例填写");
                errorData.add(valueList);
                continue;
            }
            if (Objects.nonNull(importExcelVo)) {
                // 正式员工
                if (EmploymentFormEnum.FORMAL.getCode().equals(importExcelVo.getEmploymentForm())) {
                    importExcelVo.setState(EmployeeStatusEnum.PROBATION.getCode());
                    if (Objects.isNull(importExcelVo.getProbationPeriod())) {
                        respVO.getFailureNames().put("第" + rowNum + "行" + StrUtil.nullToEmpty(importExcelVo.getName()), "【1007】" + EMPLOYEE_CHOOSE_PROBATIONARY_PERIOD.getMsg());
                        ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                        valueList.add(EMPLOYEE_CHOOSE_PROBATIONARY_PERIOD.getMsg());
                        errorData.add(valueList);
                        continue;
                    }
                    importExcelVo.setPlanRegularizationTime(importExcelVo.getEntryTime().plusMonths(importExcelVo.getProbationPeriod()).minusDays(1));

                    if (importExcelVo.getProbationPeriod().equals(EmployeeProbationPeriodEnum.No_probation_period.getMonth())) {
                        importExcelVo.setState(EmployeeStatusEnum.REGULARIZED.getCode());
                    }
                    if (Objects.nonNull(importExcelVo.getRegularizationTime())) {
                        boolean state = importExcelVo.getRegularizationTime().compareTo(LocalDateTime.now()) <= 0;
                        importExcelVo.setState(state ? EmployeeStatusEnum.REGULARIZED.getCode() : EmployeeStatusEnum.PENDING_REGULARIZATION.getCode());

                    }
                }


                // 非正式
                if (EmploymentFormEnum.INFORMAL.getCode().equals(importExcelVo.getEmploymentForm())) {
                    if (Objects.isNull(importExcelVo.getEmploymentType())) {
                        respVO.getFailureNames().put("第" + rowNum + "行" + StrUtil.nullToEmpty(importExcelVo.getName()), "【1008】" + EMPLOYEE_TYPE_NOT_EXISTS.getMsg());
                        ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                        valueList.add(EMPLOYEE_TYPE_NOT_EXISTS.getMsg());
                        errorData.add(valueList);
                        continue;
                    }
                    importExcelVo.setState(EmployeeStatusEnum.INFORMAL_EMPLOYEE.getCode());
                }
                // 数据校验
                Set<ConstraintViolation<EmployeeImportExcelVo>> validated = validator.validate(importExcelVo);
                if (CollUtil.isNotEmpty(validated)) {
                    // 基本校验不通过
                    respVO.getFailureNames().put("第" + rowNum + "行" + StrUtil.nullToEmpty(importExcelVo.getName()), "【1009】" + validated.iterator().next().getMessage());
                    ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                    valueList.add(validated.iterator().next().getMessage());
                    errorData.add(valueList);
                    continue;
                }
                // 员工编号唯一性校验
                EmployeeDO employeeNo = employeeMapper.selectByEmployeeNo(importExcelVo.getEmployeeNo());
                if (Objects.nonNull(employeeNo)) {
                    respVO.getFailureNames().put("第" + rowNum + "行" + importExcelVo.getName(), "【1010】" + EMPLOYEE_NO_CANNOT_BE_REPEATED.getMsg());
                    ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                    valueList.add(EMPLOYEE_NO_CANNOT_BE_REPEATED.getMsg());
                    errorData.add(valueList);
                    continue;
                }
                try {
                    // 插入员工
                    EmployeeImportCurdVo build = EmployeeImportCurdVo.builder().importExcelVo(importExcelVo).list(list).customFieldList(customFieldList)
                            .respVO(respVO).tenantName(tenant.getName()).loginUserName(loginUser.getNickname()).build();
                    SpringUtil.getBean(this.getClass()).curdEmployee(build);
                } catch (ServiceException e) {
                    e.printStackTrace();
                    respVO.getFailureNames().put("第" + rowNum + "行" + importExcelVo.getName(), "【1011】" + e.getMessage());
                    ArrayList<String> valueList = new ArrayList<>(dataRow.values());
                    valueList.add(e.getMessage());
                    errorData.add(valueList);
                }
            }
        }

        if (!respVO.getFailureNames().isEmpty()) {
            List<List<String>> finalHeader = new ArrayList<>();
            for (String head : excelHeadIdxNameMap.values()) {
                List<String> temp = new ArrayList<>();
                temp.add(head);
                finalHeader.add(temp);
            }
            List<String> eh = new ArrayList<>();
            eh.add("错误原因");
            finalHeader.add(eh);

            File excel = null;
            try {
                excel = File.createTempFile("Error", ".xls");
                excel.deleteOnExit();
                EasyExcel.write(new FileOutputStream(excel)).sheet("。。。。。").head(finalHeader)
                        .doWrite(errorData);
                respVO.setFileName(excel.getName());
                respVO.setFilePath(excel.getAbsolutePath());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return respVO;
    }

    @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
    public void curdEmployee(EmployeeImportCurdVo build) {
        EmployeeDO employeeDO = BeanUtil.toBean(build.getImportExcelVo(), EmployeeDO.class);
        employeeMapper.insert(employeeDO);
        // 成长轨迹
        // 创建员工成长轨迹
        EmployeeGrowthRecordSaveReqVO vo = new EmployeeGrowthRecordSaveReqVO();
        vo.setEmployeeId(employeeDO.getId());
        vo.setContent(String.format(EmployeeGrowthEnum.ADD_NEW_EMPLOYEES.getAction(), build.getTenantName()));
        vo.setAction("用户" + build.getLoginUserName() + "新建在职员工");
        vo.setEffectiveTime(employeeDO.getCreateTime());
        employeeGrowthRecordService.createEmployeeGrowthRecord(vo);
        // 风险点扫描
        employeeRiskHandleChainService.execute(Collections.singleton(employeeDO.getId()));
        build.getList().forEach(f -> f.setRecordId(employeeDO.getId()));
        // 插入自定义字段
        build.getCustomFieldList().removeIf(c -> c.getLabelGroup() == null); // 去掉手动添加进去的
        build.getList().removeIf(l -> l.getLabelGroup() == null);
        List<CustomFieldDataBaseBO> fieldDataSaveBOS = BeanUtils.toBean(build.getList(), CustomFieldDataBaseBO.class);
        List<Integer> label = build.getCustomFieldList().stream().map(CustomFieldRespDTO::getLabel).distinct().collect(Collectors.toList());
        List<Integer> labelGroup = build.getCustomFieldList().stream().map(CustomFieldRespDTO::getLabelGroup).distinct().collect(Collectors.toList());
        List<Long> recordIds = fieldDataSaveBOS.stream().map(CustomFieldDataBaseBO::getRecordId).distinct().collect(Collectors.toList());
        CustomFieldDataSaveBO saveBO = CustomFieldDataSaveBO.builder().datas(fieldDataSaveBOS)
                .bizType(BizTypeEnum.EMPLOYEE.getValue()).labelGroups(labelGroup).labels(label)
                .recordIds(recordIds).build();
        customFieldDataService.crudData(saveBO);
        // 生成账号
        EmployeeLoginInfoSaveReqVO reqVO = new EmployeeLoginInfoSaveReqVO();
        if (build.getImportExcelVo().getRoleId() != null) {
            reqVO.setRoleId(build.getImportExcelVo().getRoleId());
        }
        curdLoginInfo(reqVO, employeeDO);
        if (reqVO.getDeptId() == null) {
            reqVO.setDeptId(employeeDO.getDeptId());
        }
        createLoginInfo(reqVO);
        build.getRespVO().getCreateNames().add(employeeDO.getName());
    }

    public void curdLoginInfo(EmployeeLoginInfoSaveReqVO reqVO, EmployeeDO employeeDO) {
        String pinyin = PinyinUtil.getPinyin(employeeDO.getName()).replaceAll("\\s*", "");
        List<AdminUserRespDTO> allUserList = adminUserServiceProvider.getAllUserList(pinyin, Boolean.TRUE);
        // 检查登录用户名是否重复，是的话后面加数字区别
        String name = CollUtil.isEmpty(allUserList) ? pinyin : buildUserName(CollectionUtils.convertList(allUserList, AdminUserRespDTO::getUsername), pinyin, 2);
        reqVO.setUsername(name);
        reqVO.setNickname(employeeDO.getName());
        reqVO.setEmployeeId(employeeDO.getId());
        reqVO.setPassword("123456");
        reqVO.setRemark("系统生成账号");
    }

    public String buildUserName(List<String> usernameList, String name, Integer i) {
        if (CollUtil.isNotEmpty(usernameList)) {
            String tempName = name;
            for (String userName : usernameList) {
                if (Objects.equals(name, userName)) {
                    name = tempName + i;
                    i += 1;
                    buildUserName(usernameList, name, i);
                }
            }
            return name;
        }
        return null;
    }

    @Override
    public Long getEmployeeId() {
        return EmployeeContextHolder.getEmployeeId();
    }

    @Override
    public List<EmployeeDO> getEmployeePayee(Integer year, Integer month) {
        List<EmployeeDO> employeeList = employeeMapper.selectList();
        // 剔除掉在规定发薪年，发薪月之后入职的员工
        employeeList.removeIf(e -> e.getEntryTime().getYear() >= year && e.getEntryTime().getMonthValue() > month);
        // 去掉发薪月前已离职的员工
        List<EmployeeDO> removeList = new ArrayList<>();
        for (EmployeeDO e : employeeList) {
            if (e.getState().equals(EmployeeStatusEnum.SEPARATED.getCode())) {
                // 去掉离职年限在当前发薪年之前的用户
                int dayOfYear = e.getApplySeparationTime().getYear();
                if (e.getApplySeparationTime().getYear() < year) {
                    removeList.add(e);
                }
                // 当年离职的员工，判断是否当月离职，去掉在当前月之前离职的员工
                if (e.getApplySeparationTime().getYear() == year && e.getApplySeparationTime().getMonthValue() < month) {
                    removeList.add(e);
                }
            }
        }
        employeeList.removeAll(removeList);
        return employeeList;
    }

    @Override
    public EmployeeSeparationRespVo getEmployeeSeparation(Long employeeId) {
        List<EmployeeSeparationRecordDO> separatedList = separationRecordService.getSeparatedList(employeeId);
        if (CollUtil.isNotEmpty(separatedList)) {
            // 取最后一条
            EmployeeSeparationRecordDO recordDO = separatedList.stream().sorted(Comparator.comparing(EmployeeSeparationRecordDO::getId).reversed()).collect(Collectors.toList()).get(0);
            return BeanUtils.toBean(recordDO, EmployeeSeparationRespVo.class);
        }
        return null;
    }

    @Override
    public Boolean removeEmployeeFile(Collection<Long> ids) {
        //1. 获取文件记录
        List<FileRefRespDTO> list = fileApi.getFileRef(ids);
        if (CollUtil.isNotEmpty(list)) {
            //2. 删除文件
            fileApi.deleteFileRef(ids);
            //3. 扫描风险
            for (FileRefRespDTO fileRef : list) {
                Long empId = fileRef.getBizRecordId();
                //3.1 调动风险
                if (fileRef.getBizFileType() - 20061 == 0 || fileRef.getBizFileType() - 20081 == 0) {
                    EmployeeTransferRecordDO transferRecord = employeeTransferRecordService.getEmployeeTransferRecord(fileRef.getBizRecordId());
                    empId = transferRecord.getEmployeeId();
                }
                employeeRiskHandleChainService.execute(Collections.singleton(empId));
            }

        }
        return Boolean.TRUE;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createLoginInfo(EmployeeLoginInfoSaveReqVO reqVO) {
        Long employeeId = reqVO.getEmployeeId();
        AdminUserSaveReqDTO adminUserSaveReqDTO = null;
        if (employeeId != null) {
            //如果需要关闭权限  使用 selectEmpById方法
            EmployeeDO employeeDO = employeeMapper.selectById(employeeId);
            if (employeeDO == null) {
                throw exception(EMPLOYEE_NOT_EXISTS);
            }
            if (employeeDO.getUserId() != null) {
                throw exception(EMPLOYEE_ACCOUNT_DUPLICATE);
            }
            adminUserSaveReqDTO = EmployeeConvert.INSTANCE.convertAdminUserSaveReqDTO(employeeDO, reqVO);
        } else {
            adminUserSaveReqDTO = EmployeeConvert.INSTANCE.convertAdminUserSaveReqDTO(reqVO);
        }
//            Set<Long> set=new HashSet<>();
//            set.add(37L);
//            adminUserSaveReqDTO.setPostIds(set);
        DeptRespDTO dept = deptApi.getDept(reqVO.getDeptId()).getCheckedData();
        Long adminUserId = adminUserServiceProvider.createAdminUser(adminUserSaveReqDTO);
        dept.setLeaderUserId(adminUserId);
        deptApi.updateDept(adminUserId, dept.getId());
        if (employeeId != null) {
            EmployeeDO employeeDO = new EmployeeDO();
            employeeDO.setId(employeeId);
            employeeDO.setUserId(adminUserId);
            employeeMapper.updateById(employeeDO);
        }
    }

    @Override
    public List<Long> getEmployeeIdsByQuery(EmployeeQueryRepVo queryRepVo) {
        List<EmployeeDO> list = employeeMapper.getEmployeeIdsByQuery(queryRepVo);
        if (list.size() == 0) {
            return Collections.emptyList();
        }
        return CollectionUtils.convertList(list, EmployeeDO::getId);
    }

    /**
     * 扫描员工生日、合同续签、即将转正、入职周年提醒
     * 目前提醒到租户管理员
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void notifyMessageSendJob() {

        // 最终生成的所有消息提醒
        List<NotifySendSingleToUserReqDTO> notifyList = new ArrayList<>();

        List<EmployeeDO> employeeDOList = employeeMapper.selectList();
        employeeDOList.removeIf(e -> e.getState().equals(EmployeeStatusEnum.SEPARATED.getCode()));
        // 生日提醒（当天提醒)
        List<Long> birthdayIds = isBirthday(employeeDOList, true);
        if (CollUtil.isNotEmpty(birthdayIds)) {
            Map<String, Object> templateParams = new HashMap<>(); // 站内信内容
            templateParams.put("info", "生日");
            List<EmployeeDO> birthdayEmployee = employeeDOList.stream().filter(e -> birthdayIds.contains(e.getId())).collect(Collectors.toList());
            Map<String, Object> birthdayMap = new HashMap<>(); // 站内信对应业务模块接口入参
            birthdayMap.put("pageNo", 1);
            birthdayMap.put("pageSize", 10);
            birthdayMap.put("isNotify", true);
            birthdayMap.put("dateTime", DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd"));
            String birthdayOptions = JsonUtils.toJsonString(birthdayMap);
            notifyList.addAll(buildNotifyList(birthdayEmployee, birthdayOptions, templateParams, NotifyDetailTypeEnum.BIRTHDAY.getCode()));

        }

        // 待转正员工提醒（提前7天）
        List<EmployeeDO> regularizeEmployeeList = CollectionUtils.convertList(employeeDOList, e -> {
            if (e.getState().equals(EmployeeStatusEnum.PROBATION.getCode())) {
                LocalDateTime planRegularizationTime = e.getEntryTime().plusMonths(e.getProbationPeriod()).minusDays(1);
                if (planRegularizationTime.toLocalDate().minusDays(7).compareTo(LocalDate.now()) == 0) {
                    return e;
                }
            }
            return null;
        });
        if (CollUtil.isNotEmpty(regularizeEmployeeList)) {
            Map<String, Object> templateParams = new HashMap<>(); // 站内信内容
            templateParams.put("info", "待转正");

            Map<String, Object> regularizeMap = new HashMap<>(); // 站内信对应业务模块接口入参
            regularizeMap.put("pageNo", 1);
            regularizeMap.put("pageSize", 10);
            regularizeMap.put("dateTime", DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd"));
            notifyList.addAll(buildNotifyList(regularizeEmployeeList, JsonUtils.toJsonString(regularizeMap), templateParams, NotifyDetailTypeEnum.REGULARIZE.getCode()));
        }

        // 待续签员工合同提醒(提前30/60天)
        List<EmployeeContractRespVO> contractExpiration = getContractExpiration(true, LocalDate.now());
        if (CollUtil.isNotEmpty(contractExpiration)) {
            List<Long> employeeIds = CollectionUtils.convertList(contractExpiration, EmployeeContractRespVO::getEmployeeId);
            Map<String, Object> templateParams = new HashMap<>(); // 站内信内容
            templateParams.put("info", "合同待续签");
            Map<String, Object> regularizeMap = new HashMap<>(); // 站内信对应业务模块接口入参
            regularizeMap.put("pageNo", 1);
            regularizeMap.put("pageSize", 10);
            regularizeMap.put("isNotify", true);
            regularizeMap.put("dateTime", DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd"));

            notifyList.addAll(buildNotifyList(employeeMapper.selectBatchIds(employeeIds), JsonUtils.toJsonString(regularizeMap), templateParams, NotifyDetailTypeEnum.CONTRACT_EXPIRE.getCode()));
        }

        // 入职周年提醒（1年，2年.....当天提醒）
        List<EmployeeDO> employeeAnniversary = getEmployeeAnniversary(LocalDate.now());
        if (CollUtil.isNotEmpty(employeeAnniversary)) {
            Map<String, Object> templateParams = new HashMap<>(); // 站内信内容
            templateParams.put("info", "入职周年");

            Map<String, Object> anniversaryMap = new HashMap<>(); // 站内信对应业务模块接口入参
            anniversaryMap.put("pageNo", 1);
            anniversaryMap.put("pageSize", 10);
            anniversaryMap.put("dateTime", DateUtil.format(LocalDateTime.now(), "yyyy-MM-dd"));

            notifyList.addAll(buildNotifyList(employeeAnniversary, JsonUtils.toJsonString(anniversaryMap), templateParams, NotifyDetailTypeEnum.ANNIVERSARY.getCode()));
        }
        if (CollUtil.isNotEmpty(notifyList)) {
            notifyMessageServiceProvider.sendSingleNotifyBatch(notifyList);
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateTerminationStatus() {
        // 获取所有合同
        List<EmployeeContractRespVO> list = employeeContractService.selectEmployeeAllContract();
        list.removeIf(c -> Objects.isNull(c.getTerminationTime()));
        if (CollUtil.isNotEmpty(list)) {
            List<EmployeeContractDO> updateList = CollectionUtils.convertList(list, contract -> {
                if (contract.getTerminationTime().isBefore(LocalDateTime.now())) {
                    EmployeeContractDO updateDo = new EmployeeContractDO();
                    updateDo.setId(contract.getId());
                    updateDo.setTerminationStatus(Boolean.TRUE);
                    return updateDo;
                }
                return null;
            });
            employeeContractService.updateContractBatch(updateList);
        }
    }

    /**
     * 获取当天为员工入职周年的员工列表
     *
     * @return
     */
    public List<EmployeeDO> getEmployeeAnniversary(LocalDate date) {
        List<EmployeeDO> employeeDOList = employeeMapper.selectList();
        // 去除已离职
        employeeDOList.removeIf(e -> e.getState().equals(EmployeeStatusEnum.SEPARATED.getCode()));
        if (CollUtil.isNotEmpty(employeeDOList)) {
            return CollectionUtils.convertList(employeeDOList, e -> {
                if (Objects.nonNull(e.getEntryTime())) {
                    Period period = Period.between(e.getEntryTime().toLocalDate(), date);
                    if (period.getYears() == ChronoUnit.YEARS.between(e.getEntryTime().toLocalDate(), date)
                            && period.getYears() > 0) {
                        // 判断是否是同一天
                        if (date.getMonth() == e.getEntryTime().getMonth() && date.getDayOfMonth() == e.getEntryTime().getDayOfMonth()) {
                            return e;
                        }
                    }
                }
                return null;
            });
        }
        return Collections.emptyList();
    }

    /**
     * 构建站内信消息发送参数
     *
     * @param employeeList    员工列表
     * @param birthdayOptions 提醒消息对应模块的接口入参（点击跳转时用）
     * @param templateParams  消息内容
     * @return
     */
    public List<NotifySendSingleToUserReqDTO> buildNotifyList(List<EmployeeDO> employeeList, String birthdayOptions, Map<String, Object> templateParams, Integer detailType) {
        employeeList.removeIf(Objects::isNull);
        if (CollUtil.isNotEmpty(employeeList)) {
            // 获取租户管理员角色
            List<RoleRespDTO> roleList = roleServiceProvider.selectListByCode(RoleCodeEnum.TENANT_ADMIN.getCode());
            Map<Long, List<RoleRespDTO>> roleListMap = CollectionUtils.convertMultiMap(roleList, RoleRespDTO::getTenantId);
            Map<Long, List<EmployeeDO>> employeeListMap = CollectionUtils.convertMultiMap(employeeList, EmployeeDO::getTenantId);
            for (Long key : employeeListMap.keySet()) {
                // 消息接收人
                List<RoleRespDTO> list = roleListMap.get(key);
                if (CollUtil.isNotEmpty(list)) {
                    Set<Long> userIds = permissionServiceProvider.getUserRoleIdListByRoleIds(CollectionUtils.convertList(list, RoleRespDTO::getId));
                    if (CollUtil.isNotEmpty(userIds)) {
                        List<NotifySendSingleToUserReqDTO> notifyList = CollectionUtils.convertList(userIds, userId -> {
                            NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO();
                            reqDTO.setOptions(birthdayOptions);
                            reqDTO.setTemplateParams(templateParams);
                            reqDTO.setDetailType(detailType);
                            reqDTO.setTemplateCode(NotifyTemplateCodeEnum.EMPLOYEE_INFO_NOTIFY.getCode());
                            reqDTO.setUserId(userId);
                            return reqDTO;
                        });
                        return notifyList;
                    }
                }
            }
        }
        return Collections.emptyList();
    }


    @Override
    public void scanEmployeeState() {
        LocalDate now = LocalDate.now();
        List<EmployeeDO> employeeList = employeeMapper.selectList();
        // 最后更新用
        List<EmployeeDO> updateList = new ArrayList<>();
        // 转正
        List<EmployeeRegularizeRecordDO> recordList = regularizeRecordService.getRegularizeRecordList();
        recordList.removeIf(r -> r.getRegularizationTime().toLocalDate().compareTo(now) > 0 || !r.getApproveResult().equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus()));
        Map<Long, EmployeeRegularizeRecordDO> regularizeMap = CollectionUtils.convertMap(recordList, EmployeeRegularizeRecordDO::getEmployeeId);
        // 调动
        List<EmployeeTransferRecordDO> transferRecordList = employeeTransferRecordService.getTransferRecordList();
        transferRecordList.removeIf(t -> t.getEffectTime().toLocalDate().compareTo(now) > 0 || !t.getApproveResult().equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus()));
        Map<Long, EmployeeTransferRecordDO> transferRecordMap = CollectionUtils.convertMap(transferRecordList, EmployeeTransferRecordDO::getEmployeeId);
        // 离职
        List<EmployeeSeparationRecordDO> separationRecordList = separationRecordService.getSeparationRecordList();
        separationRecordList.removeIf(s -> s.getSeparationTime().toLocalDate().compareTo(now) > 0 || !s.getApproveResult().equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus()));
        Map<Long, EmployeeSeparationRecordDO> separationMap = CollectionUtils.convertMap(separationRecordList, EmployeeSeparationRecordDO::getEmployeeId);

        for (EmployeeDO employeeDO : employeeList) {
            try {
                // 处理待转正
                if (employeeDO.getState().equals(EmployeeStatusEnum.PENDING_REGULARIZATION.getCode())) {
                    EmployeeRegularizeRecordDO regularize = regularizeMap.get(employeeDO.getId());
                    if (Objects.nonNull(regularize)) {
                        employeeDO.setState(EmployeeStatusEnum.REGULARIZED.getCode());
                        employeeMapper.updateById(employeeDO);
                    } else {
                        if (Objects.nonNull(employeeDO.getRegularizationTime()) &&
                                employeeDO.getRegularizationTime().toLocalDate().compareTo(LocalDate.now()) <= 0) {
                            employeeDO.setState(EmployeeStatusEnum.REGULARIZED.getCode());
                            employeeMapper.updateById(employeeDO);
                        }
                    }
                }

                // 处理调动-待离职和已离职的员工不允许操作调动
                if (!employeeDO.getState().equals(EmployeeStatusEnum.TO_BE_SEPARATED.getCode()) && !employeeDO.getState().equals(EmployeeStatusEnum.SEPARATED.getCode())) {
                    EmployeeTransferRecordDO transfer = transferRecordMap.get(employeeDO.getId());
                    if (Objects.nonNull(transfer)) {
                        employeeDO.setDeptId(Objects.nonNull(transfer.getNewDeptId()) ? transfer.getNewDeptId() : employeeDO.getDeptId());
                        employeeDO.setPostId(Objects.nonNull(transfer.getNewPostId()) ? transfer.getNewPostId() : employeeDO.getPostId());
                        employeeDO.setPostLevelId(Objects.nonNull(transfer.getNewPostLevel()) ? transfer.getNewPostLevel() : employeeDO.getPostLevelId());

                        employeeMapper.updateById(employeeDO);

                        // 人事异动时，检查规章制度制定及实施风险
                        changePostForRegulationRisk(employeeDO);
                        // 如有，更新部门风险
                        riskService.changeEmpRiskDept(employeeDO.getId(), employeeDO.getDeptId());
                        // 如有，更新用户信息
                        if (employeeDO.getUserId() != null) {
                            EmployeeLoginInfoSaveReqVO reqVO = BeanUtils.toBean(employeeDO, EmployeeLoginInfoSaveReqVO.class);
                            reqVO.setId(employeeDO.getUserId());
                            reqVO.setEmployeeId(employeeDO.getId());
                            reqVO.setPassword(null);
                            updateUserInfo(reqVO, employeeDO);
                        }
                    }
                }
                // 处理离职
                if (employeeDO.getState().equals(EmployeeStatusEnum.TO_BE_SEPARATED.getCode())) {
                    EmployeeSeparationRecordDO separation = separationMap.get(employeeDO.getId());
                    if (Objects.nonNull(separation)) {
                        employeeDO.setState(EmployeeStatusEnum.SEPARATED.getCode());
                        employeeDO.setSeparationReason(separation.getSeparationReason());
                        employeeDO.setSeparationType(separation.getSeparationType());
                        employeeDO.setSeparationRemarks(separation.getRemarks());

                        employeeMapper.updateById(employeeDO);

                        disableUser(employeeDO);
                    }
                }
            } catch (Exception e) {
                System.err.println(e);
            }
        }
    }

    public void updateUserInfo(EmployeeLoginInfoSaveReqVO reqVO, EmployeeDO employeeDO) {
        AdminUserRespDTO adminUser = adminUserServiceProvider.getAdminUser(reqVO.getId());
        if (adminUser == null) {
            throw exception(EMPLOYEE_ACCOUNT_NOT_EXISTS);
        }
        AdminUserSaveReqDTO adminUserSaveReqDTO = null;
        adminUserSaveReqDTO = EmployeeConvert.INSTANCE.convertAdminUserSaveReqDTO(employeeDO, reqVO);
        adminUserSaveReqDTO.setId(reqVO.getId());
        adminUserSaveReqDTO.setUsername(adminUser.getUsername());
        adminUserSaveReqDTO.setPassword(null);
        adminUserSaveReqDTO.setStatus(adminUser.getStatus());
        adminUserServiceProvider.updateAdminUser(adminUserSaveReqDTO);
    }

    public void disableUser(EmployeeDO employeeDO) {

        EmployeeLoginInfoSaveReqVO reqVO = BeanUtils.toBean(employeeDO, EmployeeLoginInfoSaveReqVO.class);
        reqVO.setId(employeeDO.getUserId());
        reqVO.setEmployeeId(employeeDO.getId());
        reqVO.setPassword(null);
        AdminUserRespDTO adminUser = adminUserServiceProvider.getAdminUser(reqVO.getId());
        if (adminUser == null) {
            throw exception(EMPLOYEE_ACCOUNT_NOT_EXISTS);
        }
        AdminUserSaveReqDTO adminUserSaveReqDTO = null;
        adminUserSaveReqDTO = EmployeeConvert.INSTANCE.convertAdminUserSaveReqDTO(employeeDO, reqVO);
        adminUserSaveReqDTO.setId(reqVO.getId());
        adminUserSaveReqDTO.setUsername(adminUser.getUsername());
        adminUserSaveReqDTO.setPassword(null);
        adminUserSaveReqDTO.setStatus(CommonStatusEnum.DISABLE.getStatus());
        adminUserServiceProvider.updateAdminUser(adminUserSaveReqDTO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateLoginInfo(EmployeeLoginInfoSaveReqVO reqVO) {
        AdminUserRespDTO adminUser = adminUserServiceProvider.getAdminUser(reqVO.getId());
        if (adminUser == null) {
            throw exception(EMPLOYEE_ACCOUNT_NOT_EXISTS);
        }
        EmployeeDO employeeDO = employeeMapper.selectByUserId(reqVO.getId());

        AdminUserSaveReqDTO adminUserSaveReqDTO = null;

        if (employeeDO == null) {
            if (reqVO.getEmployeeId() != null) {
                EmployeeDO login = employeeMapper.selectById(reqVO.getEmployeeId());
                if (login == null) {
                    throw exception(EMPLOYEE_NOT_EXISTS);
                }
                if (login.getUserId() != null) {
                    throw exception(EMPLOYEE_ACCOUNT_DUPLICATE);
                }
                adminUserSaveReqDTO = EmployeeConvert.INSTANCE.convertAdminUserSaveReqDTO(login, reqVO);

                EmployeeDO update = new EmployeeDO();
                update.setId(reqVO.getEmployeeId());
                update.setUserId(reqVO.getId());
                employeeMapper.updateById(update);
            } else {
                adminUserSaveReqDTO = EmployeeConvert.INSTANCE.convertAdminUserSaveReqDTO(reqVO);
            }
        } else {
            if (!Objects.equals(employeeDO.getId(), reqVO.getEmployeeId())) {
                // 绑定的员工不可变更
                throw exception(EMPLOYEE_ACCOUNT_NOT_ALLOW_CHANGE);
            }
            adminUserSaveReqDTO = EmployeeConvert.INSTANCE.convertAdminUserSaveReqDTO(adminUser);
            adminUserSaveReqDTO.setRemark(reqVO.getRemark());
        }
        adminUserSaveReqDTO.setId(reqVO.getId());
        adminUserSaveReqDTO.setUsername(adminUser.getUsername());
        adminUserSaveReqDTO.setPassword(null);
        adminUserSaveReqDTO.setStatus(adminUser.getStatus());
        adminUserServiceProvider.updateAdminUser(adminUserSaveReqDTO);
    }

    @Override
    public EmployeeLoginInfoRespVO getLoginInfo(Long userId) {
        AdminUserRespDTO adminUser = adminUserServiceProvider.getAdminUser(userId);
        if (adminUser == null) {
            throw exception(EMPLOYEE_ACCOUNT_NOT_EXISTS);
        }
        EmployeeLoginInfoRespVO respVO = EmployeeConvert.INSTANCE.convertEmployeeLoginRespVO(adminUser);
        // 员工没有删除，所以不会出现绑定了之后查询不到员工信息的情况
        EmployeeDO employee = employeeMapper.selectByUserId(userId);
        if (employee != null) {
            respVO.setEmployeeId(employee.getId());
        }
        return respVO;
    }

    @Override
    public void deleteLoginInfo(Long id) {
        adminUserServiceProvider.deleteAdminUser(id);
        EmployeeDO employeeDO = employeeMapper.selectByUserId(id);
        if (employeeDO != null) {
            employeeMapper.deleteEmployeeUser(employeeDO.getId());
        }
    }

    @Override
    public List<EmployeeDO> getEmployeeSimpleList(EmployeeLikeQueryReqVO queryReqVO) {
        return employeeMapper.selectEmpSimpleList(queryReqVO);
    }

    @Override
    public PageResult<EmployeeDeptPageRespVo> employeeDeptPage(EmployeeDeptPageReqVo reqVo) {
        PageResult<EmployeeDeptPageRespVo> pageResult = new PageResult<EmployeeDeptPageRespVo>().setList(new ArrayList<>()).setTotal(0L);

        List<DeptRespDTO> childDeptList = deptServiceProvider.getChildDeptList(reqVo.getDeptId());
        List<Long> list = CollectionUtils.convertList(childDeptList, DeptRespDTO::getId);
        list.add(reqVo.getDeptId());
        reqVo.setDeptIdList(list);
        PageResult<EmployeeDO> employeeDeptPage = employeeMapper.selectEmployeeDeptPage(reqVo);
        if (!ObjectUtils.isEmpty(employeeDeptPage)) {
            employeeDeptPage.getList().forEach(employeeDO -> {
                if (!ObjectUtils.isEmpty(employeeDO.getDingUserId())) {
                    DingUser dingUser = dingUserMapper.selectById(employeeDO.getDingUserId());
                    if (!ObjectUtils.isEmpty(dingUser)) {
                        employeeDO.setDingUserName(dingUser.getName());
                    }
                }
            });
        }

        if (employeeDeptPage.getList().size() > 0) {
            // 部门信息
            List<Long> deptIds = CollectionUtils.convertList(employeeDeptPage.getList(), EmployeeDO::getDeptId);
            Map<Long, DeptRespDTO> deptMap = deptServiceProvider.getDeptMap(deptIds);
            pageResult.setList(BeanUtils.toBean(employeeDeptPage.getList(), EmployeeDeptPageRespVo.class)).setTotal(employeeDeptPage.getTotal());
            if (deptIds.size() > 0) {
                pageResult.getList().forEach(e -> e.setDeptName(e.getDeptId() == null ? null : deptMap.get(e.getDeptId()).getName()));
            }

        }

        return pageResult;
    }

    @Override
    public List<EmployeeDO> getLoginEmpList(EmployeeLikeQueryReqVO queryReqVO) {
        return employeeMapper.getLoginEmpList(queryReqVO);
    }

    @Override
    @TenantIgnore
    public Integer sendMessage(String tenantName, String phone, String account) {
        HrmMessageLog hrmMessageLog = new HrmMessageLog();
        CommonResult<TenantRespDTO> tenantByName = tenantApi.getTenantByName(tenantName);
        if (ObjectUtils.isEmpty(tenantByName.getData())) {
            throw new ResultException("租户不存在");
        }
        AdminUserRespDTO user = adminUserApi.getUserByUserInfo(account, phone, tenantByName.getData().getId());
        if (ObjectUtils.isEmpty(user) || ObjectUtils.isEmpty(user.getMobile())) {
            throw new ResultException("手机号不存在，或手机号格式有误");
        }
        String messageCode = SendMessageUtil.getrandom();
        // 获取当前时间
        Calendar calendar = Calendar.getInstance();
        // 将当前时间增加10分钟
        calendar.add(Calendar.MINUTE, 10);
        // 获取增加后的时间的时间戳
        long timeStamp = calendar.getTimeInMillis();
        System.out.println("10分钟后的时间戳：" + timeStamp);

        hrmMessageLog.setCode(messageCode);
        hrmMessageLog.setPhone(user.getMobile());
        hrmMessageLog.setSendTime(timeStamp);
        hrmMessageLog.setState(0);
        hrmMessageLog.setUserId(user.getId());
        hrmMessageLogMapper.insert(hrmMessageLog);
        SendMessageUtil.sendMessage(user.getMobile(), messageCode);
        return 1;
    }

    @Override
    @TenantIgnore
    public Integer retrievePassword(String tenantName, String phone, String account, String messageCode, String password) {
        CommonResult<TenantRespDTO> tenantByName = tenantApi.getTenantByName(tenantName);
        if (ObjectUtils.isEmpty(tenantByName.getData())) {
            throw new ResultException("租户不存在");
        }
        AdminUserRespDTO user = adminUserApi.getUserByUserInfo(account, phone, tenantByName.getData().getId());
        if (ObjectUtils.isEmpty(user) || ObjectUtils.isEmpty(user.getMobile())) {
            throw new ResultException("手机号不存在，或手机号格式有误");
        }
        HrmMessageLog hrmMessageLog = hrmMessageLogMapper.selectOne(new LambdaQueryWrapper<HrmMessageLog>() {{
            eq(HrmMessageLog::getCode, messageCode);
            eq(HrmMessageLog::getState, 0);
            last("limit 1");
        }});

        if (ObjectUtils.isEmpty(hrmMessageLog)) {
            throw new ResultException("验证码不正确");
        }
        HrmMessageLog hrmMessageLogByTime = hrmMessageLogMapper.selectOne(new LambdaQueryWrapper<HrmMessageLog>() {{
            eq(HrmMessageLog::getCode, messageCode);
            eq(HrmMessageLog::getState, 0);
            ge(HrmMessageLog::getSendTime, System.currentTimeMillis());
            last("limit 1");
        }});

        if (ObjectUtils.isEmpty(hrmMessageLog)) {
            throw new ResultException("验证码已过期");
        }

        hrmMessageLogByTime.setState(1);
        hrmMessageLogMapper.updateById(hrmMessageLogByTime);
        AdminUserSaveReqDTO adminUserSaveReqDTO = new AdminUserSaveReqDTO();
        BeanUtils.copyProperties(user, adminUserSaveReqDTO);
        adminUserSaveReqDTO.setPassword(password);
        adminUserApi.updateUser(adminUserSaveReqDTO);
        return 0;
    }


    @Override
    public Integer selectAuthorizedStatus() {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeDO employeeDO = employeeMapper.selectByUserId(loginUserId);

        if (ObjectUtils.isEmpty(employeeDO)) {
            throw new ResultException("此账号无个人认证，请更换账号重试");
        }
        if (employeeDO.getEsignRealnameStatus() == 0) {

            return 1;
        }
        if (employeeDO.getEsignAuthorizedStatus() == 0) {
            return 2;
        }
        return 3;
    }

    @Override
    @TenantIgnore
    public JSONObject selectPsnInfo() {
        JSONObject result = new JSONObject();
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeDO employeeDO = employeeMapper.selectByUserId(loginUserId);

        if (ObjectUtils.isEmpty(employeeDO)) {
            result.put("psnStatus", 0);
            result.put("psnName", "");
            result.put("psnCardNum", "");
            return result;
        } else if (employeeDO.getEsignAuthorizedStatus() == 0) {
            result.put("psnStatus", 0);
            result.put("psnName", "");
            result.put("psnCardNum", "");
            return result;
        } else {
            EsignPsnInfo esignPsnInfo = esignPsnInfoMapper.selectOne(new LambdaQueryWrapper<EsignPsnInfo>() {{
                eq(EsignPsnInfo::getPsnId, employeeDO.getEsignPsnId());
                orderByDesc(EsignPsnInfo::getPsnAuthorizedStatus);
                last(" limit 1");
            }});
            if (ObjectUtils.isEmpty(esignPsnInfo)) {
                result.put("psnStatus", 0);
                result.put("psnName", "");
                result.put("psnCardNum", "");
                return result;
            } else {
                result.put("psnStatus", 1);
                result.put("psnName", esignPsnInfo.getPsnName());
                result.put("psnCardNum", esignPsnInfo.getPsnIdCardNum());
                return result;
            }

        }
    }

    @Override
    @PermitAll
    public String getByCreateByName(Integer createById) {
        EmployeeDO employeeDO = employeeMapper.selectById(createById);
        if(ObjectUtils.isEmpty(employeeDO)){
            return "管理员";
        }

        return employeeDO.getName();
    }
}
